三个线程分别打印 A,B,C,要求这三个线程一起运行,打印 n 次,输出形如“ABCABCABC…”的字符串
💖 synchronized + wait + notifyAll 实现
PrintABCUsingWaitNotify
.java
public class PrintABCUsingWaitNotify {
private int state;// 状态对应需要打印值:0:A,1:B,2:C
private int times;// 需要打印的次数
private final Object LOCK = new Object();//共用一个锁
public PrintABCUsingWaitNotify(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingWaitNotify printABC = new PrintABCUsingWaitNotify(3);
new Thread(() -> {
printABC.printLetter("A", 0);
}, "A").start();
new Thread(() -> {
printABC.printLetter("B", 1);
}, "B").start();
new Thread(() -> {
printABC.printLetter("C", 2);
}, "C").start();
}
private void printLetter(String s, int targetState) {
for(int i = 0; i < times; i++)//保证每个线程打印 times 次
{
synchronized (LOCK)// 获取锁 避免插队
{
while (state % 3 != targetState){// 打印之前,先判断是否符合打印条件,即是否轮到此线程打印了
try {
LOCK.wait();// 没轮到 则释放锁并等待
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
System.out.println(s);// 终于等到了
state++;
LOCK.notifyAll();//唤醒等待中的锁
}
}
}
}
💖 Lock 实现
PrintABCUsingLock
.java
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PrintABCUsingLock {
private int times; // 控制打印次数
private int state; // 状态对应需要打印值:0:A,1:B,2:C
private Lock lock = new ReentrantLock();
public PrintABCUsingLock(int times) {
this.times = times;
}
private void printLetter(String s, int targetNum) {
int cnt = 0;//统计打印了多少次
while(cnt < times)
{
lock.lock();//先获取锁(保证输出和状态更新的原子性)
if(state % 3 == targetNum)// 符合条件才输出,不符直接跳过
{
System.out.print(s);
state++;
cnt++;
}
lock.unlock();
}
}
public static void main(String[] args) {
PrintABCUsingLock loopThread = new PrintABCUsingLock(3);
new Thread(() -> {
loopThread.printLetter("A", 0);
}, "A").start();
new Thread(() -> {
loopThread.printLetter("B", 1);
}, "B").start();
new Thread(() -> {
loopThread.printLetter("C", 2);
}, "C").start();
}
}
💖 Condition
PrintABCUsingLockCondition
.java
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author : lighting
*/
public class PrintABCUsingLockCondition {
private int times;
private int state;
private static Lock lock = new ReentrantLock();
// 三个Condition休息区分别对应三个线程
private static Condition c1 = lock.newCondition();
private static Condition c2 = lock.newCondition();
private static Condition c3 = lock.newCondition();
public PrintABCUsingLockCondition(int times) {
this.times = times;
}
/**
*
* @param s 要输出的字符串
* @param targetState 目标状态
* @param cur 当前的 Condition(条件等待区)
* @param next 下一个 Condition
*/
private void printLetter(String s, int targetState, Condition cur, Condition next) {
int cnt = 0;
while(cnt < times){
lock.lock();//老规矩先拿锁
try {
while (state % 3 != targetState) {
cur.await();//只要不符合条件就等待
}
System.out.println(s);
cnt++;
state++;
next.signal();//唤醒下一个休息等待的 Condition
} catch (Exception e) {
e.printStackTrace();
}finally {
lock.unlock();//切记释放锁
}
}
}
public static void main(String[] args) {
PrintABCUsingLockCondition print = new PrintABCUsingLockCondition(3);
new Thread(() -> {
print.printLetter("A", 0, c1, c2);
}, "a").start();
new Thread(() -> {
print.printLetter("B", 1, c2, c3);
}, "b").start();
new Thread(() -> {
print.printLetter("C", 2, c3, c1);
}, "c").start();
}
}