使用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 添加了一个元素..
相关推荐
然而,多线程通信也存在潜在的危险。其中最常见的问题是**竞态条件(Race Condition)**,即多个线程同时访问并修改同一数据,导致结果不可预测。另一个问题是**死锁(Deadlock)**,即两个或更多线程相互等待对方释放...
首先,标题"qt 中 多线程tcp通信"表明我们要在Qt环境中实现TCP(Transmission Control Protocol)的多线程通信。TCP是一种面向连接的、可靠的传输协议,确保数据的顺序传输和错误检查。在多线程环境下,我们可以将...
4. `QSemaphore`:控制对资源的并发访问数量,用于线程之间的资源调度。 二、Qt线程与进程间通信 线程和进程间的通信比线程间通信复杂,因为它们各自拥有独立的地址空间。Qt提供了多种方式来实现这一目标: 1. `...
java 多线程 其实就是每个线程都拥有自己的内存空间,多线程之间的通信,比例A线程修改了主内存(main方法的线程)变量,需要把A线程修改的结果同步到主线程中,这时B线程再从主线程获取该变量的值,这样就实现了...
多线程通信是另一个重要的主题,尤其在复杂的软件系统中。当一个程序需要执行多个任务并行时,多线程技术就显得尤为重要。在QT5中,QThread类被用来创建和管理线程。每个QThread对象代表一个独立的执行线程。然而,...
在Java编程中,多线程通信是一个重要的概念,特别是在并发编程中。`ThreadDemo`示例可能演示了如何在不同的线程之间有效地传递信息。线程通信是解决多个执行流同步和协作的关键,确保数据的一致性和正确性。以下是...
MFC多线程之间的通信:本程序通过2个示例展示了通过自定义消息在多线程之间传递消息。
在计算机编程中,多线程是并发执行任务的一种方式,特别是在多核...通过对"MultiThread7"这个示例的学习,开发者可以更深入地理解Windows下的线程通信机制,并将其应用到自己的项目中,提升软件的性能和用户体验。
多线程通信和等待机制是多线程编程中一个重要的概念,它们都是基于线程之间的同步和协作来实现的。其中,wait()和notify()方法是Java语言中实现多线程通信和等待机制的两个核心方法。 wait()方法是Object类的一个...
3. **线程通信**: 可以使用消息队列或者事件对象(如CEvent)来实现线程间的通信和协作。 **四、MFCAPI串口实现** 结合MFC和API,我们可以创建一个名为MFCAPI_SerialComm的类,这个类封装了串口的打开、关闭、读写...
操作系统中的多线程通信是并发编程中的核心概念,它允许不同的执行线程在共享资源时进行协调和数据交换。在本文中,我们将深入探讨多线程通信的重要性、常见方法以及如何解决经典的问题——读者写者问题。 首先,多...
在编程领域,多线程应用是提升程序性能和并发处理能力的重要手段。然而,当一个应用程序中有多个线程运行时,它们可能需要共享数据或协调工作,这就涉及到线程间通信(Inter-Thread Communication,简称ITC)。MFC...
在本文中,我们将深入探讨如何使用Visual Studio 2017和C++来实现TCP套接字的多线程通信。TCP(传输控制协议)是一种面向连接、可靠的、基于字节流的通信协议,广泛应用于互联网上的各种服务。多线程技术则允许我们...
串口通信的实现,编程环境为C#,实现技术采用了多线程方式
在IT领域,多线程UDP通信是一个重要的主题,特别是在开发高效、实时的网络应用程序时。在Windows Forms(Winform)环境中,多线程技术结合用户界面(UI)和网络通信可以提升程序性能,避免UI线程阻塞,提高用户体验...
利用多线程实现C#中socket网络通信模块,具体最大承受多少个客户端还不是很清楚,但是20个绝对没问题
在计算机科学领域,尤其是软件开发中,多线程通信是一个重要的概念,特别是在处理并发任务和优化性能时。本文将深入探讨计算机网络中的多线程通信,以Java编程语言为例,结合"MT_WebServer"这一文件,来阐述如何实现...
在C++编程中,多线程通信是并发执行任务时必不可少的一个环节,它涉及到线程间的同步和数据共享。在本篇文章中,我们将深入探讨如何在C++中实现多线程通信,以及相关的同步机制和数据交换策略。 一、线程创建与管理...
本例中简单运用了线程间通信原理,简单明了,适合初学线程通信
线程通信是指线程之间的数据交换和同步。在Linux平台下,可以使用PTHREAD_MUTEX_T类型的互斥体机制来实现多线程的互斥操作。互斥体机制的作用是对某个需要互斥的部分,在进入时先得到互斥体,如果没有得到互斥体,...