java.util.concurrent包(3)——线程间通信wait/notify和await/signal

简介:
一、线程如何停止
使用stop()不安全。它会解除由线程获取的所有锁定,而且如果对象处于一种不连贯状态,那么其他线程能在那种状态下检查和修改它们。结果很难检查出真正的问题所在。suspend()方法容易发生死锁。调用suspend()的时候,目标线程会停下来,但却仍然持有在这之前获得的锁定。此时其他任何线程都不能访问锁定的资源,除非被"挂起"的线程恢复运行。对任何线程来说,如果它们想恢复目标线程,同时又试图使用任何一个锁定的资源,就会造成死锁。所以不应该使用suspend()。正确的做法是而应在自己的Thread类中置入一个标志,指出线程应该活动还是挂起。若标志指出线程应该挂起,便用wait()命其进入等待状态。若标志指出线程应当恢复,则用一个notify()重新启动线程。jdk1.5后提供了condition对象,这个对象的await()和singal()方法也可以达到线程通信的效果。

二、wait和notify实例

子线程循环10次,主线程循环100次。接着子线程循环10次,主线程循环100次。如此循环50次。摘自张孝祥老师线程视频源码。
public class TraditionalThreadCommunication
{
public static void main(String[] args)
{
final Business business = new Business();
new Thread(new Runnable() {
public void run()
{
for (int i = 1; i <= 50; i++)
{
business.sub(i);
}
}
}).start();
for (int i = 1; i <= 50; i++)
{
business.main(i);
}
}
}

class Business
{
private boolean bShouldSub= true;

public synchronized void sub(int i)
{
while (!bShouldSub)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++)
{
System.out.println("sub thread sequence of " + j + ",loop of " + i);
}
bShouldSub = false;
this.notify();
}

public synchronizedvoid main(int i)
{
while (bShouldSub)
{
try
{
this.wait();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 100; j++)
{
System.out.println("main thread sequence of " + j + ",loop of " + i);
}
bShouldSub = true;
this.notify();
}
}

三、Condition实例
public class Condition1Test
{
public static void main(String[] args)
{
final BusinessLock business = new BusinessLock();
new Thread(new Runnable() {
public void run()
{
for (int i = 1; i <= 50; i++)
{
business.sub(i);
}
}
}).start();
for (int i = 1; i <= 50; i++)
{
business.main(i);
}
}
}

class BusinessLock
{
private boolean bShouldSub = true;

ReentrantLock lock = new ReentrantLock();
Condition condition = lock.newCondition();

public void sub(int i)
{
lock.lock();
try
{
while (!bShouldSub)
{
try
{
condition.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++)
{
System.out.println("sub thread sequence of " + j + ",loop of " + i);
}
bShouldSub = false;
condition.signal();
}
finally
{
lock.unlock();
}
}

public void main(int i)
{
lock.lock();
try
{
while (bShouldSub)
{
try
{
condition.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 100; j++)
{
System.out.println("main thread sequence of " + j + ",loop of " + i);
}
bShouldSub = true;
condition.signal();
}
finally
{
lock.unlock();
}
}
}

四、Condition实例扩展
三个线程相互通信,main循环100次,sub2循环10次,sub3循环10次。接着main循环100次,sub2循环10次,sub3循环10次。如此循环50次。
public class Condition2Test
{
public static void main(String[] args)
{
final BusinessLock2 business = new BusinessLock2();
new Thread(new Runnable() {
public void run()
{
for (int i = 1; i <= 50; i++)
{
business.main(i);
}
}
}).start();

new Thread(new Runnable() {
public void run()
{
for (int i = 1; i <= 50; i++)
{
business.sub2(i);
}
}
}).start();

new Thread(new Runnable() {
public void run()
{
for (int i = 1; i <= 50; i++)
{
business.sub3(i);
}
}
}).start();
}
}


class BusinessLock2
{
private int bShouldSub = 1;

ReentrantLock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Condition condition3 = lock.newCondition();

public void main(int i)
{
lock.lock();
try
{
while (bShouldSub != 1)
{
try
{
condition1.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 100; j++)
{
System.out.println("main thread sequence of " + j + ",loop of " + i);
}
bShouldSub = 2;
condition2.signal();
}
finally
{
lock.unlock();
}
}

public void sub2(int i)
{
lock.lock();
try
{
while (bShouldSub != 2)
{
try
{
condition2.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++)
{
System.out.println("sub2 thread sequence of " + j + ",loop of " + i);
}
bShouldSub = 3;
condition3.signal();
}
finally
{
lock.unlock();
}
}

public void sub3(int i)
{
lock.lock();
try
{
while (bShouldSub != 3)
{
try
{
condition3.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
for (int j = 1; j <= 10; j++)
{
System.out.println("sub3 thread sequence of " + j + ",loop of " + i);
}
bShouldSub = 1;
condition1.signal();
}
finally
{
lock.unlock();
}
}
}
目录
相关文章
|
10月前
|
消息中间件 算法 安全
JUC并发—1.Java集合包底层源码剖析
本文主要对JDK中的集合包源码进行了剖析。
|
11月前
|
前端开发 JavaScript Java
[Java计算机毕设]基于ssm的OA办公管理系统的设计与实现,附源码+数据库+论文+开题,包安装调试
OA办公管理系统是一款基于Java和SSM框架开发的B/S架构应用,适用于Windows系统。项目包含管理员、项目管理人员和普通用户三种角色,分别负责系统管理、请假审批、图书借阅等日常办公事务。系统使用Vue、HTML、JavaScript、CSS和LayUI构建前端,后端采用SSM框架,数据库为MySQL,共24张表。提供完整演示视频和详细文档截图,支持远程安装调试,确保顺利运行。
469 17
|
Java Android开发
Eclipse 创建 Java 包
Eclipse 创建 Java 包
241 1
|
Java
JAVA多线程通信:为何wait()与notify()如此重要?
在Java多线程编程中,`wait()` 和 `notify()/notifyAll()` 方法是实现线程间通信的核心机制。它们通过基于锁的方式,使线程在条件不满足时进入休眠状态,并在条件满足时被唤醒,从而确保数据一致性和同步。相比其他通信方式,如忙等待,这些方法更高效灵活。 示例代码展示了如何在生产者-消费者模型中使用这些方法实现线程间的协调和同步。
173 3
|
安全 Java
Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧
【10月更文挑战第20天】Java多线程通信新解:本文通过生产者-消费者模型案例,深入解析wait()、notify()、notifyAll()方法的实用技巧,包括避免在循环外调用wait()、优先使用notifyAll()、确保线程安全及处理InterruptedException等,帮助读者更好地掌握这些方法的应用。
234 1
|
安全 Java 开发者
Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用
本文深入解析了Java多线程中的`wait()`、`notify()`和`notifyAll()`方法,探讨了它们在实现线程间通信和同步中的关键作用。通过示例代码展示了如何正确使用这些方法,并分享了最佳实践,帮助开发者避免常见陷阱,提高多线程程序的稳定性和效率。
352 1
|
存储 Java 数据安全/隐私保护
|
4月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
266 1
|
4月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
283 1
|
5月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案