使用wait/notify 方法实现线程之间的通信 这两个方法都是object类的方法
换句话说 java为所有的对象都提供了这两个方法
1 wait 和notify 必须配合synchronized 关键字来使用
2 wait 方法释放锁,notify方法不释放锁
public class Test2 { private volatile static List list = new ArrayList(); @SuppressWarnings("unchecked") public void add(){ list.add("aaa"); } public int size(){ return list.size(); } public static void main(String[] args) { final Test2 test2 = new Test2(); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { for (int i = 0; i < 10; i++) { test2.add(); System.out.println("当前线程:"+Thread.currentThread().getName()+" 添加了一个元素.."); Thread.sleep(500); } } catch (InterruptedException e) { e.printStackTrace(); } } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { while (true) { if (list.size()==5) { System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" list size = 5 线程停止.. "); throw new RuntimeException(); } } } },"t2"); t1.start(); t2.start(); } }
上面一段代码的 意图是当线程t1 执行到add操作 当list.size()==5时 发出通知
通知 t2 线程结束退出
执行结果如下:
当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程收到通知:t2 list size = 5 线程停止.. Exception in thread "t2" java.lang.RuntimeException at test.Test2$2.run(Test2.java:59) at java.lang.Thread.run(Unknown Source) 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素..
使用 wait / notify 来改写后的代码如下
package test; import java.util.ArrayList; import java.util.List; @SuppressWarnings("rawtypes") public class Test2 { private volatile static List list = new ArrayList(); @SuppressWarnings("unchecked") public void add(){ list.add("aaa"); } public int size(){ return list.size(); } public static void main(String[] args) { final Test2 test2 = new Test2(); final Object lock = new Object(); Thread t1 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { for (int i = 0; i < 10; i++) { test2.add(); System.out.println("当前线程:"+Thread.currentThread().getName()+" 添加了一个元素.."); if (list.size()==5) { lock.notify(); System.out.println(" 发出通知.."); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { System.out.println(" in t2"); if (list.size()!=5) { try { System.out.println(" t2 start to wait "); lock.wait(); System.out.println(" t2 end wait "); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" list size = 5 线程停止.. "); throw new RuntimeException(); } } },"t2"); t2.start(); t1.start(); } }
执行结果如下:
in t2 t2 start to wait 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 发出通知.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. t2 end wait 当前线程收到通知:t2 list size = 5 线程停止.. Exception in thread "t2" java.lang.RuntimeException at test.Test2$2.run(Test2.java:62) at java.lang.Thread.run(Unknown Source)
事实上并没有如预期中那样 在 list size = 5 线程停止..
分析原因如下:
代码执行顺序如下
首先 t2 获得 lock 然后 执行lock.wait()释放lock 并等待 notify
然后 t1 获得 lock 执行add操作 当list.size() ==5 的时候 执行lock.notify() 此时 t1并没有释放 lock 而是执行完整个操作的时候才去释放lock 此时 t2 重新获得lock 继续执行下面的操作
这样显示没有达到我们的目的 没有及时的通知到线程t2
其实如果利用concurrent包里的countDownLatch可以用极为简单的代码来实现我们的目的
package test; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; @SuppressWarnings("rawtypes") public class Test2 { private volatile static List list = new ArrayList(); @SuppressWarnings("unchecked") public void add(){ list.add("aaa"); } public int size(){ return list.size(); } public static void main(String[] args) { final Test2 test2 = new Test2(); final CountDownLatch countDownLatch = new CountDownLatch(1); Thread t1 = new Thread(new Runnable() { @Override public void run() { for (int i = 0; i < 10; i++) { test2.add(); System.out.println("当前线程:"+Thread.currentThread().getName()+" 添加了一个元素.."); if (list.size()==5) { System.out.println(" 发出通知.."); countDownLatch.countDown(); } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } } } },"t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { System.out.println(" in t2"); if (list.size()!=5) { try { System.out.println(" t2 start to wait "); countDownLatch.await(); System.out.println(" t2 end wait "); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程收到通知:"+Thread.currentThread().getName()+" list size = 5 线程停止.. "); throw new RuntimeException(); } },"t2"); t2.start(); t1.start(); } }
执行结果如下
in t2 t2 start to wait 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 发出通知.. t2 end wait 当前线程收到通知:t2 list size = 5 线程停止.. Exception in thread "t2" java.lang.RuntimeException at test.Test2$2.run(Test2.java:59) at java.lang.Thread.run(Unknown Source) 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素.. 当前线程:t1 添加了一个元素..
相关推荐
利用一个小型游戏的服务器和客服端之间的信息通信来介绍多线程之间的信息通信,以及通信可能存在的危险。
java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,这时B线程再从主线程获取该变量的值,这样就实现了...
Qt线程之间通信、线程和进程之间通信实例,简单易懂
MFC多线程之间的通信:本程序通过2个示例展示了通过自定义消息在多线程之间传递消息。
串口通信的实现,编程环境为C#,实现技术采用了多线程方式
利用多线程实现C#中socket网络通信模块,具体最大承受多少个客户端还不是很清楚,但是20个绝对没问题
一个简单的通信demo 当时做测试用的。包括客户端和服务端。 在非主线程中使用tcp的通信,基于qt编写
Winform 的多线程udp通信
本例中简单运用了线程间通信原理,简单明了,适合初学线程通信
C++实现多线程通信
基于QT5实现的串口通信,及多线程间的通信,使用自定义信号实现。
模仿QQ的多线程通信实例,供参考。 模仿QQ的多线程通信实例,供参考。
采用的是C#的Winform开发,提供了两种线程交互的方式。 第一:在主线程中开启两个子线程,子线程用事件方式来进行通信。对于主线程的控件操作采用的是delegate委托的方式,避免主线程假死。 第二:采用的是...
多线程实现Socket通信 多线程实现Socket通信 多线程实现Socket通信
多线程线程间通信,可用于控制线程内部函数,做处理......................................................
演示了如何使用自定义消息进行线程间通信,如何在线程间传递消息,可运行,VC历程
socket多线程通信源码 socket多线程通信源码
实现了子线程与主线程之间的通信;主线程给自己发消息、主线程给子线程发消息、子线程给主线程发消息等。
Java 线程通信示例 源代码 多线程之间通信,值得收藏
包括TCP服务器客户端多线程通信程序(用select实现),基于Visual Studio2017实现,已编译测试过,用到的朋友记得关闭SDL检查