查看Condition源代码,@since 1.5,Condition是JDK1.5中才出现的,相比使用传统Object的wait(),notify(),使用Condition的await()、signal()这种方式实现线程间协作更加安全和高效。
Condition类能实现synchronized和wait、notify搭配的功能,另外比后者更灵活,Condition可以实现多路通知功能;Condition需要通过ReentrantLock的newCondition()来实现,也就是说Condition的使用是需要依赖Lock对象的。
Condition的方法,见源代码,截图如下:
- Condition实现多线路通知
package com.lyb269.thread;
import org.junit.Test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Condition多线路通知功能,每条线路互不影响
*/
public class ConditionMultilineTest {
private ReentrantLock lock = new ReentrantLock();
//线路1 Condition
private Condition lineCondition1 = lock.newCondition();
//线路2 Condition
private Condition lineCondition2 = lock.newCondition();
//线路等待
private void lineAwait(Condition condition){
try{
lock.lock();
Thread currentThread = Thread.currentThread();
long start = System.currentTimeMillis();
System.out.println(currentThread.getName()+":执行lineAwait,进入等待");
//await等待
condition.await();
//如果执行到这里说明线路被唤醒
System.out.println(currentThread.getName()+":被唤醒");
System.out.println(currentThread.getName()+":执行了"+(System.currentTimeMillis()-start)+"ms");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//线路唤醒
private void lineSignalAll(Condition condition){
try{
lock.lock();
//唤醒
condition.signalAll();
}finally {
lock.unlock();
}
}
@Test
public void test() throws InterruptedException {
Thread line1 = new Thread(() -> lineAwait(lineCondition1));
Thread line2 = new Thread(() -> lineAwait(lineCondition2));
new Thread(line1,"line1").start();
new Thread(line2,"line2").start();
// wait 2秒
Thread.sleep(2000);
// 唤醒line1
lineSignalAll(lineCondition1);
// wait 3秒
Thread.sleep(3000);
// 唤醒line2
lineSignalAll(lineCondition2);
//line1:执行lineAwait,进入等待
//line2:执行lineAwait,进入等待
//line1:被唤醒
//line1:执行了2000ms
//line2:被唤醒
//line2:执行了5000ms
//总结:
// 线路1,线路2各自进入等待
// 根据调用的顺序在sleep对应设置的时间之后各自唤醒,两条线路之间互不干涉,各自工作
}
}
- 线程协作,模拟生产者消费者
package com.lyb269.thread;
import org.junit.Test;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* Condition通知和等待实现 生产者和消费者
* 线程之间的协作
*/
public class ConditionWaitAndSignalTest {
private final ReentrantLock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
//true-表示消费,false-表示生产
private boolean flag = false;
//模拟库存指标
private int store = 0;
//生产
private void produce(){
try{
lock.lock();
if (flag){
//如果是消费,则停止生产
condition.await();
}
System.out.println("生产前库存为:"+store+";生产后库存为:"+(++store));
flag = !flag;
//模拟生产一次需耗时2秒
Thread.sleep(2000);
//生产完毕,提醒消费
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
//消费
private void consume(){
try{
lock.lock();
if (!flag){
//如果生产,则停止消费
condition.await();
}
System.out.println("消费前库存为:"+store+";消费后库存为:"+(--store));
flag = !flag;
//模拟消费一次需耗时1.5秒
Thread.sleep(1500);
//消费完毕,提醒生产
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
@Test
public void test(){
new Thread(() -> {
//生产线程,一直生产
while (true){
produce();
}
}).start();
new Thread(() -> {
//消费线程,一直消费
while (true){
consume();
}
}).start();
//结果如下交替打印:
//生产前库存为:0;生产后库存为:1
//消费前库存为:1;消费后库存为:0
//生产前库存为:0;生产后库存为:1
//消费前库存为:1;消费后库存为:0
}
}