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();
}
}
}
目录
相关文章
|
2天前
|
druid Java Maven
杨校老师课堂之java_关于如何下载jar包的教程
杨校老师课堂之java_关于如何下载jar包的教程
14 0
|
2天前
|
安全 Java
JAVA多线程通信新解:wait()、notify()、notifyAll()的实用技巧
【6月更文挑战第20天】Java多线程中,`wait()`, `notify()`和`notifyAll()`用于线程通信。在生产者-消费者模型示例中,它们确保线程同步。`synchronized`保证安全,`wait()`在循环内防止虚假唤醒,`notifyAll()`避免唤醒单一线程问题。关键技巧包括:循环内调用`wait()`,优先使用`notifyAll()`以保证可靠性,以及确保线程安全和正确处理`InterruptedException`。
|
2天前
|
Java 程序员
从菜鸟到大神:JAVA多线程通信的wait()、notify()、notifyAll()之旅
【6月更文挑战第21天】Java多线程核心在于wait(), notify(), notifyAll(),它们用于线程间通信与同步,确保数据一致性。wait()让线程释放锁并等待,notify()唤醒一个等待线程,notifyAll()唤醒所有线程。这些方法在解决生产者-消费者问题等场景中扮演关键角色,是程序员从新手到专家进阶的必经之路。通过学习和实践,每个程序员都能在多线程编程的挑战中成长。
|
1天前
|
Oracle Java 关系型数据库
面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?
面试知识点:notify是随机唤醒线程吗(唤醒线程顺序)?
8 0
|
1天前
|
Java
Java Socket编程与多线程:提升客户端-服务器通信的并发性能
【6月更文挑战第21天】Java网络编程中,Socket结合多线程提升并发性能,服务器对每个客户端连接启动新线程处理,如示例所示,实现每个客户端的独立操作。多线程利用多核处理器能力,避免串行等待,提升响应速度。防止死锁需减少共享资源,统一锁定顺序,使用超时和重试策略。使用synchronized、ReentrantLock等维持数据一致性。多线程带来性能提升的同时,也伴随复杂性和挑战。
|
2天前
|
Java 数据库连接 Spring
杨校老师课堂之Java EE框架SSM所需jar包下载
杨校老师课堂之Java EE框架SSM所需jar包下载
9 0
|
2天前
|
安全 Java
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
【6月更文挑战第20天】JAVA多线程中,wait(), notify(), notifyAll()是Object类的关键同步机制。wait()让线程等待并释放锁,直到被notify()或notifyAll()唤醒或超时。它们必须在同步块中使用,持有锁的线程调用。notify()唤醒一个等待线程,notifyAll()唤醒所有。最佳实践包括:与synchronized结合,循环检查条件,避免循环内notify(),通常优先使用notifyAll()。
|
1天前
|
安全 Java 程序员
Java多线程详解
Java多线程详解
|
1天前
|
缓存 安全 Java
Java线程面试题含答案
Java线程面试题含答案
|
2天前
|
Java
并发编程的艺术:Java线程与锁机制探索
【6月更文挑战第21天】**并发编程的艺术:Java线程与锁机制探索** 在多核时代,掌握并发编程至关重要。本文探讨Java中线程创建(`Thread`或`Runnable`)、线程同步(`synchronized`关键字与`Lock`接口)及线程池(`ExecutorService`)的使用。同时,警惕并发问题,如死锁和饥饿,遵循最佳实践以确保应用的高效和健壮。
8 2

热门文章

最新文章