上一篇讲解了Condition接口各个API的功能,本文继续对ReentrantLock+Condition的具体使用进行深入分析。
实现2个线程依次输出123456…
在系列文章的第二篇中,分析了采用synchronized与wait+notify实现一个经典的题目:如何控制2个线程依次输出1 2 3 4 5 6…?既然ReentrantLock可以代替synchronized,Condition可以代替wait+notify,可以实现更精细的并发协同控制,那么我们就来用ReentrantLock+Condition来实现这一个经典的题目。
ReentrantLock+Condition方案
我们回顾下这个题目的思路:
步骤1:创建2个线程t1,t2。
步骤2:t1运行输出1,t1停止输出(等待t2输出完,进入等待状态)。
步骤3:t2运行输出2,t2停止输出(等待t1输出完,进入等待状态)。
步骤4:循环执行步骤2和步骤3,即t1和t2依次执行”运行<->等待“动作。
这其中有两个等待,一个是“t1等待t2”,一个是“t2等待t1”,结合前面所学的Condition可以创建多个等待条件变量,可以创建两个Condition条件用来表示“t1等待t2”和“t2等待t1”。Condition提供了让线程进入等待状态的await()方法和唤醒其他线程的signal()方法,可以用来代替Object来的wait()方法和notify()方法。基于上面分析,我们对之前的代码改造如下:
public class ReentrantLockCollaboration {
//输出数字
private static int num = 1;
//公共变量,线程执行标识
private static boolean thread1Run = true;
//锁对象
private static final ReentrantLock lockObject = new ReentrantLock();
// 线程1运行条件
private static final Condition thread1RunCondition = lockObject.newCondition();
// 线程2运行条件
private static final Condition thread2RunCondition = lockObject.newCondition();
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while (num < 10) {
//获取锁对象
lockObject.lock();
try {
//判断是否轮到自己执行
while (!thread1Run) {
try {
//没到就进入等待
thread1RunCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " output " + num++);
thread1Run = false;
//执行完输出,通知t2执行
thread2RunCondition.signal();
} finally {
lockObject.unlock();
}
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
while (num < 10) {
//获取锁对象
lockObject.lock();
try {
//判断是否轮到自己执行
while (thread1Run) {
//没到就进入等待
try {
thread2RunCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " output " + num++);
thread1Run = true;
//执行完输出,通知t2执行
thread1RunCondition.signal();
} finally {
lockObject.unlock();
}
}
}
}, "t2");
t1.start();
t2.start();
}
}
运行结果:
t1 output 1
t2 output 2
t1 output 3
t2 output 4
t1 output 5
t2 output 6
t1 output 7
t2 output 8
t1 output 9
t2 output 10
结果符合我们的预期。
实现3个线程依次输出123456…
上面的例子中只有2个线程,一个线程输出完成后就唤醒另外的一个线程,现在我们对题目升级下:用3个线程依次输出1 2 3 4 5 6…那该如何实现?
按之前的方法我们对题目进行步骤拆解分析:
步骤1:创建3个线程t1,t2,t3。
步骤2:t1运行输出1,t1停止输出,进入等待状态(等待t2,t3输出完成)。
步骤3:t2运行输出2,t2停止输出,进入等待状态(等待t3,t1输出完成)。
步骤4:t3运行输出3,t3停止输出,进入等待状态(等待t1,t2输出完成)。
步骤5:循环执行步骤2、步骤3、步骤4,整个过程只有一个线程处于输出状态,另外两个线程处于等待状态。
<
最低0.47元/天 解锁文章
2201

被折叠的 条评论
为什么被折叠?



