JUC-线程协作-2-Condition

在线程运行过程中,需要等待某个条件的时候,就可以用 Condition ,调用它的 await() 方法,进入阻塞状态等待,当另一个线程去执行对应的条件,直到这个条件达成的时候就去执行它的 signal() 方法,这时候JVM会从被阻塞的线程中找等待该条件的线程,然后唤醒,继续执行

常用方法

  • await(): 调用后进入阻塞状态
  • signalAll(): 唤起全部的正在等待的线程
  • signal(): 公平的,唤起一个等待时间最长的线程

使用案例

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Slf4j
public class ConditionTest {
private ReentrantLock lock = new ReentrantLock();
private Condition condition = lock.newCondition();

void doSomeThing1() {
lock.lock();
try {
log.info("条件不满足,等待...");
condition.await();

log.info("条件满足,继续执行...");
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}

void doSomeThing2(){
lock.lock();
try {
log.info("准备工作完成,唤醒其他的线程...");
condition.signal();
} finally {
lock.unlock();
}
}

public static void main(String[] args) {
ConditionTest conditionTest = new ConditionTest();
new Thread(conditionTest::doSomeThing1).start();
new Thread(conditionTest::doSomeThing2).start();
}
}

控制台运行输出如下:

1
2
3
11:34:34.581 [Thread-0] INFO com.learning.java.cooperation.ConditionTest - 条件不满足,等待...
11:34:34.613 [Thread-1] INFO com.learning.java.cooperation.ConditionTest - 准备工作完成,唤醒其他的线程...
11:34:34.613 [Thread-0] INFO com.learning.java.cooperation.ConditionTest - 条件满足,继续执行...

注意点

  1. 实际上,如果说 Lock 用来代替 synchronized, 那么 Condition 就是用来代替相对应的 Object.wait/notify 的,所以在用法和性质上,几乎都一样
  2. await() 方法会自动释放持有的Lock锁,和 Object.wait 一样,不需要自己手动先释放锁
  3. 调用 await() 的时候,必须先持有锁,否则会抛异常