1.什么是线程间通信?
多个线程在处理同一资源,但是任务却不同。
生活中栗子:有一堆煤,有2辆车往里面送煤,有2辆车往外拉煤,这个煤就是同一资源,送煤和拉煤就是任务不同。
2.等待/唤醒机制。
涉及的方法:
(1)wait(): 让线程处于冻结状态,被wait的线程会被存储到线程池(容器)中。
(2)notify():唤醒线程池中一个线程(任意).
(3)notifyAll():唤醒线程池中的所有线程。
这些方法都必须定义在同步中。
因为这些方法是用于操作线程状态的方法。
必须要明确到底操作的是哪个锁上的线程。
什么是线程池?
顾名思义就是事先创建若干个可执行的线程放入一个池(容器)中,需要的时候从池中获取线程而不用自行创建,使用完毕后不需要销毁放入池中,从而减少创建和销毁对象的开销。
为什么操作线程的方法wait notify notifyAll定义在了Object类中?
因为这些方法是监视器的方法。监视器其实就是锁,就是栗子中的r。
锁可以是任意的对象,任意的对象调用的方式一定定义在Object类中。
栗子:(谁拿锁谁执行)
class Resource { private String name; private String sex; private boolean flag = false; public synchronized void set(String name,String sex) { if(flag)//为真的时候,就直接进入wait,这样该线程就释放了执行权了。为假就执行下面的语句 try{this.wait();}catch(InterruptedException e){} this.name = name; this.sex = sex; flag = true; this.notify();//唤醒输出线程,输出线程具备了执行资格。抢来了CPU执行权 } public synchronized void out() { if(!flag) try{this.wait();}catch(InterruptedException e){} System.out.println(name+"...+...."+sex); flag = false; notify();//唤醒输入线程 } } //输入 class Input implements Runnable { Resource r ; // Object obj = new Object(); Input(Resource r) { this.r = r; } public void run() { int x = 0; while(true) { if(x==0) { r.set("mike","nan"); } else { r.set("丽丽","女女女女女女"); } x = (x+1)%2; } } } //输出 class Output implements Runnable { Resource r; // Object obj = new Object(); Output(Resource r) { this.r = r; } public void run() { while(true) { r.out(); } } } class ResourceDemo3 { public static void main(String[] args) { //创建资源。 Resource r = new Resource(); //创建任务。 Input in = new Input(r); Output out = new Output(r); //创建线程,执行路径。 Thread t1 = new Thread(in); Thread t2 = new Thread(out); //开启线程 t1.start(); t2.start(); } }
3.sleep()和wait()比较
(1)对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。
(2)sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持着,当指定的时间到了又会自动恢复运行状态。
(3)在调用sleep()方法的过程中,线程不会释放对象锁。
而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
(4)wait可以指定时间也可以不指定时间,sleep必须指定时间。
(5)在同步中时,对cpu的执行权和锁的处理不同。
wait:释放执行权,释放锁。
sleep:释放执行权,不释放锁。
栗子:
A.sleep是线程类的方法,wait是object的方法
B.sleep不释放对象锁,wait放弃对象锁
C.sleep暂停线程,但监控状态依然保持,结束后会自动恢复
D.wait进入等待锁定池,只有针对此对象发出notify方法获得对象锁进入运行状态
原因:是D中,准备获取对象锁进入运行状态,而不是立即进入
4.线程状态