Java多线程通讯---------wait,notify区别
class Res{ public String username; public String sex; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //写操作 int count=0; while (true){ // synchronized (res.getClass()){ if(count==0){//偶数 res.username="小明"; res.sex="男"; } else {//奇数 res.username="小红"; res.sex="女"; } count=(count+1)%2; // } } } } class Input extends Thread{ Res res; public Input(Res res){ this.res=res; } @Override public void run() { while (true){ // synchronized (res.getClass()){ System.out.println(res.username+","+res.sex); // } } } } public class OutInputThread { public static void main(String[] args) { Res res = new Res(); Out out = new Out(res); Input input = new Input(res); out.start(); input.start(); } }
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
小红,女
出现以上结果??消费者一直消费或者生产者一直生产
解决方法:生产者生产完成后消费者方可消费,否者不可消费,消费者未消费或者未消费完生产者不可生产,一次生产一次消费。其实也就是保证对res共享资源的操作同一时刻仅有同一个线程进行操作,
wait、notify、notifyAll方法
wait、notify、notifyAll是三个定义在Object类里的方法,可以用来控制线程的状态。
这三个方法最终调用的都是jvm级的native方法。随着jvm运行平台的不同可能有些许差异。
如果对象调用了wait方法就会使持有该对象的线程把该对象的控制权交出去,然后处于等待状态。当前线程从运行变为阻塞,释放所的资源
如果对象调用了notify方法就会通知某个正在等待这个对象的控制权的线程可以继续运行。让持有该锁的线程从阻塞态变为就绪。
如果对象调用了notifyAll方法就会通知所有等待这个对象控制权的线程继续运行。
注意:一定要在线程同步中使用,并且是同一个锁的资源
通过以下方式即可完成需求。
生产者获取res.getClass锁后,如果flag为true生产者通过调用res.getClass.wait进行等待,此时其他线程可获取该锁,如果flag为false,进行生产,然后设置flag为true保证资源消费后方可再生产,接着通过notify通知其他唤醒其他线程。
class Res{ public String username; public String sex; //true 生产者等待,消费者可消费 false生产者可以生产,消费者不可消费 public boolean flag=false; } class Out extends Thread{ Res res; public Out(Res res){ this.res=res; } @Override public void run() { //写操作 int count=0; while (true){ synchronized (res.getClass()){ if(res.flag){ try { res.getClass().wait();//让当前线程从运行变为阻塞,并且释放所的资源 } catch (InterruptedException e) { e.printStackTrace(); } } if(count==0){//偶数 res.username="小明"; res.sex="男"; } else {//奇数 res.username="小红"; res.sex="女"; } count=(count+1)%2; res.flag=true; res.getClass().notify(); } } } } class Input extends Thread{ Res res; public Input(Res res){ this.res=res; } @Override public void run() { while (true){ synchronized (res.getClass()){ if(!res.flag){ try { res.getClass().wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(res.username+","+res.sex); res.flag=false; res.getClass().notify(); } } } } public class OutInputThread { public static void main(String[] args) { Res res = new Res(); Out out = new Out(res); Input input = new Input(res); out.start(); input.start(); } } 输出如下: 小明,男 小红,女 小明,男 小红,女 小明,男 小红,女 小明,男 小红,女
如果去掉notify会怎样?去掉一个?去掉两个?
去掉一个生产者可以打印多个(但是也不多),去掉消费者仅可打印一个,去掉两个可能不打印,也可能打印1个,所以wait、notify必须成对使用
wait(用于同步中)与sleep区别?
都是做休眠,wait需要notify
对于sleep方法,我们首先要知道该方法是属于Thread类中的。而wait方法,则是属于Object类中的。
sleep方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。
在调用sleep方法的过程中,线程不会释放对象锁。
而当调用wait方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。
推荐阅读
-
Java多线程通讯---------wait,notify区别
-
java中的sleep()和wait()的区别
-
多线程----wait/notify
-
Java 中Object的wait() notify() notifyAll()方法使用
-
详解Java中wait和sleep的区别
-
Java的wait(), notify()和notifyAll()使用心得
-
浅谈Java线程间通信之wait/notify
-
java多线程之wait(),notify(),notifyAll()的详解分析
-
基于Java多线程notify与notifyall的区别分析
-
Java的wait(), notify()和notifyAll()使用心得