[Java]线程间协作(通信)

通过保证在临界区上多个线程的相互排斥,线程同步完全可以避免竞争状态的发生,但有时还需要线程之间的协作。

使用Condition便于线程间通信,它是通过调用Lock对象的newCondition()方法而创建的对象。

创建Condition后,就可以使用await() 、signal()、 signalAll()方法来实现线程间的相互通信。

java.util.concurrent.Condition
+await():void 让当前线程处于等待状态,直到条件发生
+signal():void 唤醒一个等待的线程
+signalAll():Condition 唤醒所有等待的线程  

为使用Condition,必须首先获取锁。
线程间通信的流程就可以总结为:

一个线程要访问某需要同步处,申请获取锁,访问时发现不满足自己可以执行的条件,进入等待状态并释放锁;
而唤醒程序的流程一般是首先去获取锁,访问后条件发生改变,唤醒 await等待中的线程,等待中的线程由此重新获取锁,最后释放锁。

例子,存取款任务线程间的通信:

import java.util.concurrent.*;
import java.util.concurrent.locks.*;

public class ThreadCooperation {
private static Account account=new Account();

public static void main(String[] args){
ExecutorService executor=Executors.newFixedThreadPool(2);
executor.execute(new DepositTask());
executor.execute(new WithdrawTask());
executor.shutdown();

System.out.println("Thread 1\t\tThread 2\t\tBalance");
}

public static class DepositTask implements Runnable{
public void run(){
try{
while(true){
account.deposit((int)(Math.random()*10)+1);
Thread.sleep(1000);
}
}
catch(InterruptedException ex){
ex.printStackTrace();
}
}
}
public static class WithdrawTask implements Runnable{
public void run(){

while(true){
account.withdraw((int)(Math.random()*10)+1);
}
}
}

private static class Account{
//创建锁
private static Lock lock=new ReentrantLock();
//创建条件
private static Condition newDeposit=lock.newCondition();

private int balance=0;

public int getBalance(){
return balance;
}
//取款
public void withdraw(int amount){
//获取锁
lock.lock();
try{
while(balance<amount){
System.out.println("\t\tWait for a deposit"); 
//线程进入等待状态,暂时释放锁直到被唤醒
newDeposit.await();
}
balance-=amount;
System.out.println("\t\tWithdraw "+amount+"\t\t"+getBalance());
}
catch(InterruptedException ex){
ex.printStackTrace();
}
finally{
//释放锁
lock.unlock();
}
}
//存款
public void deposit(int amount){
//获取锁
lock.lock();
try{
balance+=amount;
System.out.println("Deposit "+amount+"\t\t\t\t\t"+getBalance());
//条件发生变化,唤醒等待的线程们
newDeposit.signalAll();
}
finally{
//释放锁
lock.unlock();
}
}
}
}

await()方法让线程等待并且自动释放Condition上的锁。一旦条件正确,线程重新获取锁并继续执行。
注意:
线程调用条件上的await()就进入等待状态,等待恢复信号。若忘记对条件使用signal()或signalAll(),那么线程就会一直等待下去。
条件由Lock对象创建。为了调用任意方法(如await、signal、signalAll),必须先拥有锁。若没有获取锁就调用这些方法,会抛出IllegalMonitorStateException异常。

Java 5之前使用的内置监视器(monitor)中对象上的wait()、notify()和notifyAll()方法类似于状态上的await()、signal()和signalAll()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值