今日份鸡汤:这个世界从不缺少看笑话的人,做不到雪中送炭,也请不要雪上加霜,请保持住那最后一点的善良。
思路:控制线程精确的执行(阻塞或者唤醒),想到的是lock提供的condition,利用await()方法和signal()来实现精准的顺序执行,但是考虑到不是一直顺序循环执行,查看一下规律,然后进行分组:T1->T2->T3(第一组,index=1), T3->T2->T1(第二组,index=2),T1->T2->T3(第三组,index=3),T3->T2->T1(第四组,index=4),这样就知道了index为奇数时:T1执行完唤醒T2,T2执行完唤醒T3,T3执行完唤醒T3;index为偶数时:T1执行完唤醒T1,T2执行完唤醒T1,T3执行完唤醒T2。上代码:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 线程顺序执行:线程1 -》 线程2 -》线程3 -》线程3 -》线程2 -》线程1
*/
public class SignalTest {
private int num = 1;
private Lock lock = new ReentrantLock();
private Condition condition1 = lock.newCondition();
private Condition condition2 = lock.newCondition();
private Condition condition3 = lock.newCondition();
public void executeTh1(int index) {
try {
lock.lock();
while (num != 1) {
condition1.await();
}
System.out.println(Thread.currentThread().getName() + " 开始执行啦,当前index=" + index);
if (index % 2 == 1) {
num = 2;
condition2.signal();
} else {
num = 1;
condition1.signal();
}
} catch (Exception e){
} finally {
lock.unlock();
}
}
public void executeTh2(int index) {
try {
lock.lock();
while (num != 2) {
condition2.await();
}
System.out.println(Thread.currentThread().getName() + " 开始执行啦,当前index=" + index);
if (index % 2 == 1) {
num = 3;
condition3.signal();
} else {
num = 1;
condition1.signal();
}
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public void executeTh3(int index) {
try {
lock.lock();
while (num != 3) {
condition3.await();
}
System.out.println(Thread.currentThread().getName() + " 开始执行啦,当前index=" + index);
if (index % 2 == 1) {
num = 3;
condition3.signal();
} else {
num = 2;
condition2.signal();
}
} catch (Exception e) {
} finally {
lock.unlock();
}
}
public static void main(String[] args) {
SignalTest signalTest = new SignalTest();
new Thread(() -> {
for(int i = 1 ; i <= 5 ; i++){
signalTest.executeTh1(i);
}
}, "线程1").start();
new Thread(() -> {
for(int i = 1 ; i <= 5 ; i++){
signalTest.executeTh2(i);
}
}, "线程2").start();
new Thread(() -> {
for(int i = 1 ; i <= 5 ; i++){
signalTest.executeTh3(i);
}
}, "线程3").start();
}
}
执行结果打印:
image.png
还有一种相对简单的,顺序循环执行线程:T1->T2->T3->T1->T2->T3
懂了上面的案例,想必这种情况就更简单了,去掉index的判断逻辑,然后顺序唤醒就可以啦~
网友评论