Java多线程之wait/notify/notifyAll
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了Java多线程之wait/notify/notifyAll,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含5888字,纯文字阅读大概需要9分钟。
内容图文
![Java多线程之wait/notify/notifyAll](/upload/InfoBanner/zyjiaocheng/1144/64cae505fc7c4fd39316201a3c8334f9.jpg)
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.concurrent.TimeUnit; 4 5 /** 6 * 创建一个容器,一根线程往里放东西,一根线程判断是否符合条件 7 */ 8 public class MyContainer2 { 9 10 /* volatile */ List<Object> list = new ArrayList<>(); //内存不可见1112void add(Object o) { 13try { 14 TimeUnit.SECONDS.sleep(1); 15 } catch (InterruptedException e) { 16 e.printStackTrace(); 17 } 18 list.add(o); 19 System.out.println(Thread.currentThread().getName() + " add:" + o); 20 } 2122int getSize() { 23returnthis.list.size(); 24 } 2526publicstaticvoid main(String[] args) { 2728 MyContainer2 container = new MyContainer2(); 2930new Thread(() -> { 31for(int i=0; i<10; i++) { 32 container.add("Object" + i); 33 } 34 }, "线程1").start(); 3536new Thread(() -> { 37while (true) { //很浪费cpu资源38if(container.getSize() > 5) break; 39 } 40 System.out.println(Thread.currentThread().getName() + "结束"); 41 }, "线程2").start(); 42 } 43 }
看明白接着看,上面代码while(true)很消耗cpu资源,下面代码用到wait和notify,阻塞线程和唤醒线程:
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.concurrent.TimeUnit; 4 5 /** 6 * wait 线程会失去锁 7 * 8 * notify/notifyAll 叫醒线程 不会释放锁 9 * 10 */ 11 public class MyContainer3 { 12 13 volatile List<Object> list = new ArrayList<>(); 1415void add(Object o) { 16try { 17 TimeUnit.SECONDS.sleep(1); 18 } catch (InterruptedException e) { 19 e.printStackTrace(); 20 } 21 list.add(o); 22 System.out.println(Thread.currentThread().getName() + " add:" + o); 23 } 2425int getSize() { 26returnthis.list.size(); 27 } 2829publicstaticvoid main(String[] args) { 3031 MyContainer3 container = new MyContainer3(); 3233final Object block = new Object(); //锁3435new Thread(() -> { 36synchronized (block) { 37 System.out.println(Thread.currentThread().getName() + "开始"); 38if(container.getSize() < 5) { 39try { 40 System.out.println(Thread.currentThread().getName() + "阻塞"); 41 block.wait(); 42 } catch (InterruptedException e) { 43 e.printStackTrace(); 44 } 45 } 46 System.out.println(Thread.currentThread().getName() + "结束"); 47 } 48 }, "线程2").start(); 4950new Thread(() -> { 51synchronized (block) { 52for(int i=0; i<10; i++) { 53 container.add("Object" + i); 5455if(i > 5) { 56 block.notify(); //当唤醒在block上等待的线程后,线程1并不会失去锁,需要等线程1执行完毕释放锁,线程2才能接着执行。57 } 5859try { 60 TimeUnit.SECONDS.sleep(1); 61 } catch (InterruptedException e) { 62 e.printStackTrace(); 63 } 64 } 65 } 66 }, "线程1").start(); 6768 } 6970 }
看明白接着看,上面线程执行效果不理想,下面进行了修改:
import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; /** * wait 失去锁 * * notify/notifyAll 叫醒线程 不会释放锁 * * wait和notify/notifyAll要在synchronized代码块里 * * MyContainer3 改良版 * */ public class MyContainer4 { volatile List<Object> list = new ArrayList<>(); void add(Object o) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } list.add(o); System.out.println(Thread.currentThread().getName() + " add:" + o); } int getSize() { returnthis.list.size(); } publicstaticvoid main(String[] args) { MyContainer4 container = new MyContainer4(); final Object block = new Object(); //锁new Thread(() -> { synchronized (block) { System.out.println(Thread.currentThread().getName() + "开始"); if(container.getSize() < 5) { try { System.out.println(Thread.currentThread().getName() + "阻塞"); block.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(Thread.currentThread().getName() + "结束"); block.notify(); //唤醒线程1,继续执行 } }, "线程2").start(); new Thread(() -> { synchronized (block) { for(int i=0; i<10; i++) { container.add("Object" + i); if(container.getSize() == 5) { block.notify(); //当唤醒在block上等待的线程后,线程1并不会失去锁,需要等线程1执行完毕释放锁,线程2才能接着执行。try { block.wait(); //唤醒线程2,释放掉线程1的锁 } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } } } }, "线程1").start(); } }
看明白接着看,下面代码用到CountDownLatch,实现上面wait和notify的效果:
1 import java.util.ArrayList; 2 import java.util.List; 3 import java.util.concurrent.CountDownLatch; 4 import java.util.concurrent.TimeUnit; 5 6 /** 7 * 8 * MyContainer4 改良版 9 * 10 * 较MyContainer4 效率更高 11 * 12 */ 13 public class MyContainer5 { 14 15 volatile List<Object> list = new ArrayList<>(); 1617void add(Object o) { 18try { 19 TimeUnit.SECONDS.sleep(1); 20 } catch (InterruptedException e) { 21 e.printStackTrace(); 22 } 23 list.add(o); 24 System.out.println(Thread.currentThread().getName() + " add:" + o); 25 } 2627int getSize() { 28returnthis.list.size(); 29 } 3031publicstaticvoid main(String[] args) { 3233 MyContainer5 container = new MyContainer5(); 3435//final Object block = new Object(); //锁36 CountDownLatch latch = new CountDownLatch(5); 3738new Thread(() -> { 39//synchronized (block) {40 System.out.println(Thread.currentThread().getName() + "开始"); 41if(container.getSize() < 5) { 42//try {43 System.out.println(Thread.currentThread().getName() + "阻塞"); 44try { 45 latch.await(); //等待门闩打开46 } catch (InterruptedException e) { 47 e.printStackTrace(); 48 } 49//block.wait(); 50//} catch (InterruptedException e) { 51//e.printStackTrace(); 52//}53 } 54 System.out.println(Thread.currentThread().getName() + "结束"); 55//block.notify(); //唤醒线程1,继续执行 56//}57 }, "线程2").start(); 5859new Thread(() -> { 60//synchronized (block) {61for(int i=0; i<10; i++) { 62 container.add("Object" + i); 6364//if(container.getSize() == 5) { 65//block.notify(); //当唤醒在block上等待的线程后,线程1并不会失去锁,需要等线程1执行完毕释放锁,线程2才能接着执行。 66//try { 67//block.wait(); //唤醒线程2,释放掉线程1的锁 68//} catch (InterruptedException e) { 69//e.printStackTrace(); 70//} 71//}7273 latch.countDown(); //打开门闩,让线程2继续执行7475try { 76 TimeUnit.SECONDS.sleep(1); 77 } catch (InterruptedException e) { 78 e.printStackTrace(); 79 } 80 } 81//}82 }, "线程1").start(); 8384 } 8586 }
原文:https://www.cnblogs.com/mxh-java/p/12246370.html
内容总结
以上是互联网集市为您收集整理的Java多线程之wait/notify/notifyAll全部内容,希望文章能够帮你解决Java多线程之wait/notify/notifyAll所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。