多个线程顺序打印问题
2018-07-25 本文已影响137人
伊凡的一天
三个线程分别打印A,B,C,要求这三个线程一起运行,打印n次,输出形如“ABCABCABC....”的字符串。
1. 解法一:使用Lock
public class PrintABCUsingLock {
private int times;
private int state;
private Lock lock = new ReentrantLock();
public PrintABCUsingLock(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingLock printABC = new PrintABCUsingLock(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
print("A", 0);
}
public void printB() {
print("B", 1);
}
public void printC() {
print("C", 2);
}
private void print(String name, int targetState) {
for (int i = 0; i < times;) {
lock.lock();
if (state % 3 == targetState) {
state++;
i++;
System.out.print(name);
}
lock.unlock();
}
}
}
2. 解法二:使用wait/notify
public class PrintABCUsingWaitNotify {
private int times;
private int state;
private Object objectA = new Object();
private Object objectB = new Object();
private Object objectC = new Object();
public PrintABCUsingWaitNotify(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingWaitNotify printABC = new PrintABCUsingWaitNotify(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
try {
print("A", 0, objectA, objectB);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printB() {
try {
print("B", 1, objectB, objectC);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printC() {
try {
print("C", 2, objectC, objectA);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String name, int targetState, Object current, Object next)
throws InterruptedException {
for (int i = 0; i < times;) {
synchronized (current) {
while (state % 3 != targetState) {
current.wait();
}
state++;
i++;
System.out.print(name);
synchronized (next) {
next.notify();
}
}
}
}
}
解法三:使用Lock/Condition
public class PrintABCUsingLockCondition {
private int times;
private int state;
private Lock lock = new ReentrantLock();
private Condition conditionA = lock.newCondition();
private Condition conditionB = lock.newCondition();
private Condition conditionC = lock.newCondition();
public PrintABCUsingLockCondition(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingLockCondition printABC = new PrintABCUsingLockCondition(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
print("A", 0, conditionA, conditionB);
}
public void printB() {
print("B", 1, conditionB, conditionC);
}
public void printC() {
print("C", 2, conditionC, conditionA);
}
private void print(String name, int targetState, Condition current,
Condition next) {
for (int i = 0; i < times;) {
lock.lock();
try {
while (state % 3 != targetState) {
current.await();
}
state++;
i++;
System.out.print(name);
next.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
解法四:使用Semaphore
public class PrintABCUsingSemaphore {
private int times;
private Semaphore semaphoreA = new Semaphore(1);
private Semaphore semaphoreB = new Semaphore(0);
private Semaphore semaphoreC = new Semaphore(0);
public PrintABCUsingSemaphore(int times) {
this.times = times;
}
public static void main(String[] args) {
PrintABCUsingSemaphore printABC = new PrintABCUsingSemaphore(10);
new Thread(printABC::printA).start();
new Thread(printABC::printB).start();
new Thread(printABC::printC).start();
}
public void printA() {
try {
print("A", semaphoreA, semaphoreB);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printB() {
try {
print("B", semaphoreB, semaphoreC);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public void printC() {
try {
print("C", semaphoreC, semaphoreA);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void print(String name, Semaphore current, Semaphore next)
throws InterruptedException {
for (int i = 0; i < times; i++) {
current.acquire();
System.out.print(name);
next.release();
}
}
}