作用:使当前线程进入等待状,并交换执行执,等待被交换的当前执行线程唤醒,才可以继续执行,如果不被唤醒?
场景:多个线程操作同一个共享资源时使用。

Condition 是执行条件。类似传统技术中的 wait 的 notify 功能。
Condition 是基于一个 lock 而存在。
注意的是,Condition 的创建来自同一个 lock 对象,

Condition 也行 wait 也好,套路就是使用三个工具来完成三步套路。即,用两个线程,同时跑两个代码,并且用 while 不段的去读取一个条件,来判断自己是否应该唤醒对方。

步骤:

  1. 先lock住
  2. 通过 lock 拿到 condition。再进行操作如 await
  3. 然后多个线程开始 await、single
    注意 await 会释放锁。
1
await()的作用是能够让其他线程访问竞争资源,所以挂起状态就是要释放竞争资源的锁。
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
package com.liukai.thread.lock.condition;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
* Created by liukai on 2016/2/25.
* 测试 Lock、Condition 代替 synchronized、wait
* 例子来自 JDK Condition API 中的示例代码,阻塞队列的原理。
* 注间的是,两个不同的方法里面的 等待 和 唤醒 是不同的对象
*/
public class TestCondition {

private final Lock lock = new ReentrantLock();
private final Condition full = lock.newCondition();
private final Condition notFull = lock.newCondition();
private int count = 0;
private int takeptr = 0;
private int putptr = 0;
Object [] blockArray = new Object[100];

public static void main(String[] args) {
final TestCondition condition = new TestCondition();
for (int i = 0; i < 100; i++) {
new Thread(()->{
try {
condition.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();

new Thread(()->{
try {
condition.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();

}
}

public void put (Object element) throws InterruptedException {
try {
lock.lock();
while (count == blockArray.length) {
System.out.println("put: putptr = " + putptr + ", await");
full.await(); //等待和唤醒用的不是同一个对象
}
System.out.println("put: putptr = " + putptr + ", 执行 put");
blockArray[putptr] = element;
if (++putptr == blockArray.length) {
putptr = 0;
}
++count;
notFull.signal();
} finally {
lock.unlock();
}
}

public Object take() throws InterruptedException {
lock.lock();
Object data = null;
try {
while (0 == count) {
System.out.println("take: takeptr == " + takeptr + ",await");
notFull.await();
}
System.out.println("take: takeptr = " + takeptr + ", 执行 take");
data = blockArray[takeptr];
if (++takeptr == blockArray.length) {
takeptr = 0;
}
--count;
full.signal();
return data;
} finally {
lock.unlock();
}
}
}