一、注解
二、多线程
1、什么是多线程
1、概念:如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程” 多个线程交替占用CPU资源,而非真正的并行执行
2、多线程的好处
(1)、充分利用CPU资源
(2)、简化编程模型
(3)、用户体验度较高
3、main也是多线程的一种———主线程
4、创建线程的两种方式
1、继承 Thread类
2 、实现Runnable 接口
3、定义MyThread类继承Thread类 重写run()方法,编写线程执行体 创建线程对象,调用start()方法启动线程
其中包含 : 获得当前线程名字 Thread.currentThread().getName()
让线程休息100毫秒Thread.sleep(100);
创建线程Thread t1=new LianXi1();
启动线程t1.start();
优先级t1.setPriority(MAX_PRIORITY);
阻断线程join()
public class LianXi1 extends Thread {/** 继承Thread类实现多线程*/public void run(){for (int i = 0; i < 100; i++) {//获得当前线程的名字 Thread-0Thread t=Thread.currentThread();System.out.println(t.getName()+"----"+i);try {//让线程休息100毫秒Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {//创建线程Thread t1=new LianXi1();//Thread-0Thread t2=new LianXi1();//Thread-1// Thread t3=new LianXi1();//Thread-2//启动线程执行run方法t1.start();// t2.start();// t3.start();//设置优先级 //设置线程的优先级Thread.MAX_PRIORITY==10;//优先级越高,获得CPU资源的概率越高// t1.setPriority(MAX_PRIORITY);//10// t2.setPriority(MIN_PRIORITY);//1// t3.setPriority(NORM_PRIORITY);//5//阻断线程for (int i = 0; i <10; i++) {if(i==5){try {//阻断线程,谁调join谁先执行/** 主线程和t1线程先交替进行,当i=5时,主线程停止运行* 此时t1线程仍会执行到100,然后main线程再继续执行*/t1.join();} catch (InterruptedException e) {e.printStackTrace();}}//输出当前线程名System.out.println(Thread.currentThread().getName()+"====="+i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
4、定义MyRunnable类实现Runnable接口 实现run()方法,编写线程执行体 创建线程对象,调用start()方法启动线程
//实现Runnable接口,实现多线程public class LianXi2 implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {Thread t=Thread.currentThread();System.out.println(t.getName()+"---"+i);}}public static void main(String[] args) {Thread t1=new Thread(new LianXi2());Thread t2=new Thread(new LianXi2());t1.start();t2.start();}
5、两种创建线程的区别
继承Thread类 编写简单,可直接操作线程 适用于单继承 ;实现Runnable接口 避免单继承局限性 便于共享资源
5、创建线程的另一种方式(了解)
继承Callable
public class LianXi4 implements Callable<String> {/** 实现Callable<String>接口实现多线程*/public static void main(String[] args) {LianXi4 lx=new LianXi4();FutureTask<String> ft=new FutureTask<String>(lx);Thread t=new Thread(ft);t.start();try {//可以得到回复通知System.out.println(ft.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}@Overridepublic String call() throws Exception {for (int i = 0; i < 100; i++) {System.out.println(Thread.currentThread().getName()+"---"+i);}return "ok";}
6、创建线程有哪几种方式?
继承java.lang.Thread类 实现java.lang.Runnable接口
7、如何启动线程?
8、线程对象调用start()方法和调用run()方法的区别?
start()方法来启动线程,真正实现了多线程运行,跟其他线程交替执行;run()方法当作普通方法的方式调用,程序还是要顺序执行
9、线程的5种状态
10、线程的调度
11、什么是优先级?在线程调度中的作用?
线程优先级由1~10表示,1最低,默认优先级为5;优先级高的线程获得CPU资源的概率较大
12、join()方法和yield()方法的区别是什么?
join()阻塞,阻塞父线程,使当前线程暂停执行,等待其他线程结束后再继续执行本线程;塞阻塞主线程,子线程强制执行主线;yield()暂停当前线程,线程处于就绪状态,不转为阻塞状态程,子线程强制执行
13、练习:看病叫号
public class CureThread implements Runnable {Object obj = null;public CureThread(Object obj){super();this.obj = obj;}@Overridepublic void run() {//模拟特需号看病for(int i = 1 ;i <= 10; i++){synchronized (obj) {System.out.println(Thread.currentThread().getName()+ i +"号人在看病");try {Thread.sleep(4000);} catch (InterruptedException e) {e.printStackTrace();}}}}public class CureThreadTest {static Object obj = new Object();public static void main(String[] args) {Thread t1 = new Thread(new CureThread(obj),"特需号");t1.setPriority(Thread.MAX_PRIORITY);//t1.setName("特需号");t1.start();//主线程模拟普通号Thread.currentThread().setName("普通号");for(int i = 1; i <= 50;i++){synchronized (obj) {System.out.println(Thread.currentThread().getName() + i +"号人在看病");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}if (i==10) {try {t1.join();} catch (InterruptedException e) {e.printStackTrace();}}}}}
三、锁
2、为什么要线程同步?
3、线程同步的两种方式?
(1)、访问修饰符+synchronized
(2)、synchronized 代码块
4、线程安全和线程不安全?

5、lock和synchronized的区别?
synchronized是关键字;1.8优化后,锁升级(偏向锁—>轻量级锁/(CAS)自旋锁—>重量级锁),不可逆的
* lock是java的类/接口;手动加锁手动释放,因为syn不可逆
//线程非安全ArrayList list=new ArrayList();//线程安全的Vector vector=new Vector();//※考点安全非安全对比,和是否存入null???//线程非安全的(key和value均可以为null)HashMap map1=new HashMap();map1.put(null, null);//线程安全的,底层源码加了锁同步方法,维度更大,控制value为null,会抛出空指针异常Hashtable map2=new Hashtable();map2.put(null, null);//线程安全的;1.7采用的是分段锁机制,1.8自旋锁-->synchronized代码块 ,效率更高//key或value为null,会抛出空指针异常ConcurrentHashMap map3=new ConcurrentHashMap();map3.put(null, null);//线程非安全的StringBuilder sb2=new StringBuilder();//线程安全的 ,源码方法加了synchronized修饰StringBuffer sb1=new StringBuffer();}
6、练习,抢票系统

/** 有10张票。没卖出一张就记上*/public class SaleTicket implements Runnable{//已经售卖的票数int saleNum=0;int count=10;//总票数@Overridepublic void run() {while(sale()){}}//synchronized java关键字,/** 1、修饰方法,方法叫同步方法,给方法加锁* 2、同步代码块,可以锁局部,可以降低锁的粒度/维度,提高运行效率* lock和synchronized的区别* synchronized是关键字;1.8优化后,锁升级(偏向锁-->轻量级锁/(CAS)自旋锁-->重量级锁),不可逆的* lock是java的类/接口;手动加锁手动释放,因为syn不可逆** 不加wait()和notify()也能实现*/private boolean sale(){//什么时候卖完什么时候跳出synchronized (this) {//唤醒等待队列的线程// notify();if(count<=0){System.out.println("票已售完");return false;}count--;saleNum++;//模拟卖票的网络延时和业务处理时间try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}//买完票输谁买的,出售出几张,剩余几张System.out.println(Thread.currentThread().getName()+"--剩余---"+count+"张,已售出第"+saleNum+"张");// try {// //让线程进入等待队列// wait();// } catch (InterruptedException e) {// e.printStackTrace();// }return true;}}public static void main(String[] args) {SaleTicket st=new SaleTicket();Thread t1 = new Thread(st,"张嘉元");Thread t2 = new Thread(st,"吴宇恒");Thread t3 = new Thread(st,"黄牛党");t1.start();t2.start();t3.start();}
7、总结
8、synchronized 和Lock的区别
※lock和synchronized的区别
synchronized是关键字;1.8优化后,锁升级(偏向锁—>轻量级锁/(CAS)自旋锁—>重量级锁),不可逆的
lock是java的类/接口;手动加锁手动释放,因为syn不可逆
