问题描述: 写三个线程打印 “ABC”,一个线程打印 A,一个线程打印 B,一个线程打印 C。
方案一:Semaphore
Semaphore
(信号量) 可以用来控制同时访问特定资源的线程数量。
import java.util.concurrent.Semaphore;
public class ABCPrinter {
private final int times; // 打印次数
private final Semaphore semaphoreA = new Semaphore(1);
private final Semaphore semaphoreB = new Semaphore(0);
private final Semaphore semaphoreC = new Semaphore(0);
public ABCPrinter(int times) {
this.times = times;
}
private void printA() {
print("A", semaphoreA, semaphoreB);
}
private void printB() {
print("B", semaphoreB, semaphoreC);
}
private void printC() {
print("C", semaphoreC, semaphoreA);
}
public void print(String value, Semaphore current, Semaphore next) {
for (int i = 0; i < times; i++) {
try {
current.acquire();
System.out.println(Thread.currentThread().getName() + ": " + value);
next.release();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
ABCPrinter printer = new ABCPrinter(3);
new Thread(printer::printA, "Thread-A").start();
new Thread(printer::printB, "Thread-B").start();
new Thread(printer::printC, "Thread-C").start();
}
}
方案二:ReentrantLock
+ Condition
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class ABCPrinter {
private final int times; // 打印次数
private int state = 0; // 当前状态值
private final ReentrantLock LOCK = new ReentrantLock();
private final Condition conditionA = LOCK.newCondition();
private final Condition conditionB = LOCK.newCondition();
private final Condition conditionC = LOCK.newCondition();
public ABCPrinter(int times) {
this.times = times;
}
private void printA() {
print("A", conditionA, conditionB);
}
private void printB() {
print("B", conditionB, conditionC);
}
private void printC() {
print("C", conditionC, conditionA);
}
public void print(String value, Condition current, Condition next) {
for (int i = 0; i < times; i++) {
LOCK.lock();
try {
while (!((state == 0 && value.equals("A"))
|| (state == 1 && value.equals("B"))
|| (state == 2 && value.equals("C")))) {
current.await();
}
System.out.println(Thread.currentThread().getName() + ": " + value);
state = (state + 1) % 3;
next.signal();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
LOCK.unlock();
}
}
}
public static void main(String[] args) {
ABCPrinter printer = new ABCPrinter(3);
new Thread(printer::printA, "Thread-A").start();
new Thread(printer::printB, "Thread-B").start();
new Thread(printer::printC, "Thread-C").start();
}
}
方案三:synchronized
+ wait/notify
public class ABCPrinter {
private final int times; // 打印次数
private int state = 0; // 0: print A, 1: print B, 2: print C
private final Object LOCK = new Object();
public ABCPrinter(int times) {
this.times = times;
}
private void printA() {
print("A", 0);
}
private void printB() {
print("B", 1);
}
private void printC() {
print("C", 2);
}
public void print(String value, int expectedState) {
for (int i = 0; i < times; i++) {
synchronized (LOCK) {
try {
while (state != expectedState) {
LOCK.wait();
}
System.out.println(Thread.currentThread().getName() + ": " + value);
state = (state + 1) % 3;
LOCK.notifyAll();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
public static void main(String[] args) {
ABCPrinter printer = new ABCPrinter(3);
Thread t1 = new Thread(printer::printA, "Thread-A");
Thread t2 = new Thread(printer::printB, "Thread-B");
Thread t3 = new Thread(printer::printC, "Thread-C");
// 按照相反的顺序启动线程: C->B->A
t3.start();
t2.start();
t1.start();
// 输出:
// Thread-A: A
// Thread-B: B
// Thread-C: C
// ...重复3次...
}
}