多个线程顺序打印问题
三个线程分别打印A,B,C,要求这三个线程一起运行,打印n次,输出形如“ABCABCABC....”的字符串。
解法一:使用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(); } } }
解法二:使用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(); } } }