多线程之线程通信wait和notify的使用

ゝ一纸荒年。 2022-05-22 08:07 317阅读 0赞

使用wait和notify方法实现线程之间的通信,注意,这两个方法是Object类的方法,也就是说Java为所有的对象都提供的这两个方法。

1 wait和notify必须配合synchronized关键字使用。

2 wait方法释放锁,notify方法不释放锁。

3 还要注意一点 就是涉及到线程之间的通信,就肯定会用到validate修饰。

案例:
t1线程向集合中不断添加元素,当集合中元素个数为5的时候,就向t2线程发出通知,(当集合元素个数不等于5时候,t2线程处于等待状态),然后t2向下执行,抛出异常。

  1. package com.wuk.Demo;
  2. import java.util.ArrayList;
  3. import java.util.List;
  4. /** * wait和notify的使用 * * @author Administrator * */
  5. public class MyThread004 {
  6. private static volatile List list=new ArrayList();
  7. public void add() {
  8. list.add("wuk");
  9. }
  10. public int size() {
  11. return list.size();
  12. }
  13. public static void main(String[] args) {
  14. MyThread004 list1=new MyThread004();
  15. Object obj=new Object();
  16. Thread t1=new Thread(new Runnable() {
  17. @Override
  18. public void run() {
  19. synchronized (obj) {
  20. System.out.println("t1线程启动。。。。");
  21. for(int i=0;i<10;i++) {
  22. list1.add();
  23. System.out.println("当前线程"+Thread.currentThread().getName()+"添加了一个元素");
  24. try {
  25. Thread.sleep(500);
  26. if(list1.size()==5) {
  27. System.out.println("已经发出通知。。");
  28. obj.notify();
  29. }
  30. } catch (InterruptedException e) {
  31. // TODO Auto-generated catch block
  32. e.printStackTrace();
  33. }
  34. }
  35. }
  36. }
  37. },"t1");
  38. Thread t2=new Thread (new Runnable() {
  39. @Override
  40. public void run() {
  41. synchronized (obj) {
  42. System.out.println("t2启动。。。");
  43. if(list1.size()!=5) {
  44. try {
  45. obj.wait();
  46. } catch (InterruptedException e) {
  47. // TODO Auto-generated catch block
  48. e.printStackTrace();
  49. }
  50. }
  51. System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
  52. throw new RuntimeException();
  53. }
  54. }
  55. },"t2");
  56. t2.start();
  57. t1.start();
  58. }
  59. }

打印结果:

  1. t2启动。。。
  2. t1线程启动。。。。
  3. 当前线程t1添加了一个元素
  4. 当前线程t1添加了一个元素
  5. 当前线程t1添加了一个元素
  6. 当前线程t1添加了一个元素
  7. 当前线程t1添加了一个元素
  8. 已经发出通知。。
  9. 当前线程t1添加了一个元素
  10. 当前线程t1添加了一个元素
  11. 当前线程t1添加了一个元素
  12. 当前线程t1添加了一个元素
  13. 当前线程t1添加了一个元素
  14. 当前线程:t2收到通知线程停止..
  15. Exception in thread "t2" java.lang.RuntimeException
  16. at com.wuk.Demo.MyThread004$2.run(MyThread004.java:79)
  17. at java.lang.Thread.run(Unknown Source)

分析:
首先启动t2线程,使得t2线程处于等待状态,然后当集合等于5的时候,t1向t2线程发出通知,但是并不会释放锁,所以当t1执行完毕后,t2线程才会向下执行。

分析几种情况:
(1) 有人说 validate不是可以实现线程之间的可见性吗,那么我就不需要t1通知,当t2发现集合元素是5了就会往下执行?
去掉obj.notify(); 结果是:

  1. t2启动。。。
  2. t1线程启动。。。。
  3. 当前线程t1添加了一个元素
  4. 当前线程t1添加了一个元素
  5. 当前线程t1添加了一个元素
  6. 当前线程t1添加了一个元素
  7. 当前线程t1添加了一个元素
  8. 已经发出通知。。
  9. 当前线程t1添加了一个元素
  10. 当前线程t1添加了一个元素
  11. 当前线程t1添加了一个元素
  12. 当前线程t1添加了一个元素
  13. 当前线程t1添加了一个元素

分析:
因为当t2执行了wait()方法,就会处于等待状态,如果不去唤醒他,他就会一直等待下去。

(2)如果我们先让t1执行会是什么结果?

  1. t1线程启动。。。。
  2. 当前线程t1添加了一个元素
  3. 当前线程t1添加了一个元素
  4. 当前线程t1添加了一个元素
  5. 当前线程t1添加了一个元素
  6. 当前线程t1添加了一个元素
  7. 已经发出通知。。
  8. 当前线程t1添加了一个元素
  9. 当前线程t1添加了一个元素
  10. 当前线程t1添加了一个元素
  11. 当前线程t1添加了一个元素
  12. 当前线程t1添加了一个元素
  13. t2启动。。。

分析:
因为notify不释放锁,如果t1先执行,就会先拥有锁,那么只有等到t1执行完毕以后,t2才会有机会执行,这时候集合长度早都不是5了,所以就会一直等待下去。

发表评论

表情:
评论列表 (有 0 条评论,317人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线通信 waitnotify

    一、概念   线程是操作系统中独立的个体,这些线程如果不通过特殊的手段进行处理,就无法组成一个完整的整体。因此线程通信就称为组成一个整体的必须条件之一。当线程之间存在通