大家好,我是程序员阿药。今天和大家分享的是我遇到过的一个多线程问题,感觉挺有意思的,希望各位小伙伴喜欢。
问题描述:
给定三个线程t1、t2、t3;t1输出a,t2输出b,t3输出c;然后再由t1输出a,t2输出b。。。以此循环输出5次。
最终结果:abcabcabcabcabc。
话不多说,开码!
方式一:
使用wait()和notifyAll()实现
public static void testWaitAndNotify() {
WaitNotify waitNotify = new WaitNotify(1, 5);
new Thread(() -> {
waitNotify.print("a", 1, 2);
}, "t1").start();
new Thread(() -> {
waitNotify.print("b", 2, 3);
}, "t2").start();
new Thread(() -> {
waitNotify.print("c", 3, 1);
}, "t3").start();
}
/**
* 输出内容 等待标记 下一个标记
* a 1 2
* b 2 3
* c 3 1
*/
public void print(String content, int waitFlag, int nextFlag) {
for (int i = 0; i < loop; i++) {
synchronized (this) {
// 判断当前线程的等待标记和待打印标记是否一致
while (waitFlag != this.flag) {
try {
// 不一致则等待
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 一致则打印
System.out.print(content);
// 修改待打印标记,置为一下次要打印的标记
this.flag = nextFlag;
// 通知其他线程打印
this.notifyAll();
}
}
}
方式二:
使用ReentrantLock中的await()和signal()实现
public static void testAwaitAndSignal() {
// 创建锁
AwaitSignal awaitSignal = new AwaitSignal(5);
// 用这把锁创建三个休息室
Condition condition = awaitSignal.newCondition();
Condition condition1 = awaitSignal.newCondition();
Condition condition2 = awaitSignal.newCondition();
// 创建三个打印线程
new Thread(() -> {
awaitSignal.print("a", condition, condition1);
}, "t1").start();
new Thread(() -> {
awaitSignal.print("b", condition1, condition2);
}, "t2").start();
new Thread(() -> {
awaitSignal.print("c", condition2, condition);
}, "t3").start();
// 上面三个线程启动,但是都在等待,所以需要被唤醒
try {
Thread.sleep(1000);
// 主线程得到锁
awaitSignal.lock();
System.out.println("running start");
// 主线程先唤醒第一个线程
condition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
awaitSignal.unlock();
}
}
public void print(String content, Condition cur, Condition next) {
for (int i = 0; i < loop; i++) {
// 上锁
lock();
try {
// 当前线程进入等待
cur.await();
// 当前线程被唤醒后,执行打印
System.out.print(content);
// 唤醒下一个线程
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
// 释放锁
unlock();
}
}
}
方式三:
使用LockSupport中的park()和unpark()实现
public static void testParkAndUnpark() {
ParkUnPark parkUnPark = new ParkUnPark(5);
t1 = new Thread(() -> {
parkUnPark.print("a", t2);
}, "t1");
t2 = new Thread(() -> {
parkUnPark.print("b", t3);
}, "t2");
t3 = new Thread(() -> {
parkUnPark.print("c", t1);
}, "t3");
t1.start();
t2.start();
t3.start();
System.out.println("running start");
LockSupport.unpark(t1);
}
public void print(String content, Thread next) {
for (int i = 0; i < loop; i++) {
LockSupport.park();
System.out.print(content);
LockSupport.unpark(next);
}
}
大家如果有其它的实现方式可以在评论区互相交流哦。喜欢的小伙伴可以点赞、收藏支持一下!
需要完整源码的小伙伴可以关注我的微信公众号:“程序员阿药”,回复 “abc问题” 即可获得完整源码。