多线程交替循环打印ABC
业务需求
之前使用线程池时,更多的是关注执行的最终结果,至于每一个阶段到底是哪一个线程执行,其实我们并不关心,一般都是框架本身随机选取线程池;
现在有一个需求是交替循环打印,例如ABCABCABC......
解决方案
方案一
核心:synchronized关键字、Object类中的wait和notify方法
查看代码
/**
* 交替循环打印ABC 10次
* /
void contextLoads() {
// 计数器
private static int count = 0;
// 锁
private static final Object lock = new Object();
Thread a = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
// 申请获得锁
synchronized (lock) {
// 判断当前是否该打印
// 特别强调:此处不能用if代替while!!!虽然当线程被唤醒时需要去重新获得锁,但代码是继续向下执行的,所以得循环
while (count % 3 != 0) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第" + i + "次打印:" + "A");
count++;
// 唤醒所有正在等待的线程,最终只有一个线程能获得锁,其他线程继续等待
lock.notifyAll();
}
}
});
Thread b = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (count % 3 != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
count++;
lock.notifyAll();
}
}
});
Thread c = new Thread(() -> {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (count % 3 != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("C");
count++;
lock.notifyAll();
}
}
});
// 启动线程
a.start();
b.start();
c.start();
}
方案二
核心:ReentrantLock、Condition对象的await和signal方法
查看代码
void contextLoads() {
/**
* 阻塞线程被唤醒后需要重新获取锁,只有在拿到锁后才能从上次停止的地方继续执行
*/
private static int count = 0;
private static final ReentrantLock lock = new ReentrantLock();
Condition A = lock.newCondition();
Condition B = lock.newCondition();
Condition C = lock.newCondition();
Thread a = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
lock.lock();
while (count % 3 != 0) {
try {
// 注意阻塞的主体
A.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第" + i + "次打印:" + "A");
count++;
// 注意唤醒的主体
B.signal();
lock.unlock();
}
});
Thread b = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
lock.lock();
while (count % 3 != 1) {
try {
B.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第" + i + "次打印:" + "B");
count++;
C.signal();
lock.unlock();
}
});
Thread c = new Thread(() -> {
for (int i = 1; i <= 10; i++) {
lock.lock();
while (count % 3 != 2) {
try {
C.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("第" + i + "次打印:" + "C");
count++;
A.signal();
lock.unlock();
}
});
// 启动线程
a.start();
b.start();
c.start();
}

浙公网安备 33010602011771号