面试常考题,整理几种常见实现,侵删
1. 使用wait()和notify()
public class PrintABCUsingWaitNotify {/*** 实现步骤:* 定义一个共享对象用来同步。* 使用wait()让线程进入等待状态。* 使用notify()唤醒下一个线程。*/private final Object lock = new Object();private int state = 0; // 0:A 1:B 2:C@Testpublic void testPrintABC() {PrintABCUsingWaitNotify task = new PrintABCUsingWaitNotify();Thread threadA = new Thread(task::printA);Thread threadB = new Thread(task::printB);Thread threadC = new Thread(task::printC);threadA.start();threadB.start();threadC.start();}public void printA() {synchronized (lock) {for (int i = 0; i < 10; i++) {while (state != 0) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print("A");state = 1;lock.notifyAll();}}}public void printB() {synchronized (lock) {for (int i = 0; i < 10; i++) {while (state != 1) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print("B");state = 2;lock.notifyAll();}}}public void printC() {synchronized (lock) {for (int i = 0; i < 10; i++) {while (state != 2) {try {lock.wait();} catch (InterruptedException e) {e.printStackTrace();}}System.out.print("C");state = 0;lock.notifyAll();}}}}
2. 使用ReentrantLock和Condition
public class PrintABCUsingReentrantLock {/*** 实现步骤* 定义一个ReentrantLock和多个Condition。* 每个线程等待相应的Condition,当符合条件时打印字符并唤醒下一个线程。*/private final Lock lock = new ReentrantLock();private final Condition conditionA = lock.newCondition();private final Condition conditionB = lock.newCondition();private final Condition conditionC = lock.newCondition();private int state = 0; // 0:A 1:B 2:C@Testpublic void testPrintABC() throws InterruptedException {PrintABCUsingReentrantLock task = new PrintABCUsingReentrantLock();Thread threadA = new Thread(task::printA);Thread threadB = new Thread(task::printB);Thread threadC = new Thread(task::printC);threadA.start();threadB.start();threadC.start();}public void printA() {lock.lock();try {for (int i = 0; i < 10; i++) {while (state != 0) {conditionA.await();}System.out.print("A");state = 1;conditionB.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void printB() {lock.lock();try {for (int i = 0; i < 10; i++) {while (state != 1) {conditionB.await();}System.out.print("B");state = 2;conditionC.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}public void printC() {lock.lock();try {for (int i = 0; i < 10; i++) {while (state != 2) {conditionC.await();}System.out.print("C");state = 0;conditionA.signal();}} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}}
3. ReentrantLock和Condition的另一种写法
public class SyncPrinter implements Runnable {private final int PRINT_COUNT = 10;private final ReentrantLock reentrantLock;private final Condition thisCondition;private final Condition nextCondition;private final char printChar;public SyncPrinter(ReentrantLock reentrantLock, Condition thisCondition, Condition nextCondition, char printChar) {this.reentrantLock = reentrantLock;this.thisCondition = thisCondition;this.nextCondition = nextCondition;this.printChar = printChar;}@Overridepublic void run() {reentrantLock.lock();try {for (int i = 0; i < PRINT_COUNT; i++) {System.out.println(printChar);nextCondition.signal();if (i < PRINT_COUNT - 1) {try {thisCondition.await();} catch (InterruptedException e) {e.printStackTrace();}}}} finally {reentrantLock.unlock();}}public static void main(String[] args) throws InterruptedException {ReentrantLock lock = new ReentrantLock();Condition conditionA = lock.newCondition();Condition conditionB = lock.newCondition();Condition conditionC = lock.newCondition();Thread printA = new Thread(new SyncPrinter(lock, conditionA, conditionB, 'A'));Thread printB = new Thread(new SyncPrinter(lock, conditionB, conditionC, 'B'));Thread printC = new Thread(new SyncPrinter(lock, conditionC, conditionA, 'C'));printA.start();Thread.sleep(100);printB.start();Thread.sleep(100);printC.start();}}
4. 使用信号量Semaphore
public class PrintABCUsingSemaphore {/*** 实现步骤* 定义三个信号量semA、semB、semC。* 每个线程在自己的信号量上等待,打印完成后释放下一个线程的信号量。*/private final Semaphore semA = new Semaphore(1);private final Semaphore semB = new Semaphore(0);private final Semaphore semC = new Semaphore(0);@Testpublic void testPrintABC() throws InterruptedException {PrintABCUsingSemaphore task = new PrintABCUsingSemaphore();Thread threadA = new Thread(task::printA);Thread threadB = new Thread(task::printB);Thread threadC = new Thread(task::printC);threadA.start();threadB.start();threadC.start();}public void printA() {try {for (int i = 0; i < 10; i++) {semA.acquire();System.out.print("A");semB.release();}} catch (InterruptedException e) {e.printStackTrace();}}public void printB() {try {for (int i = 0; i < 10; i++) {semB.acquire();System.out.print("B");semC.release();}} catch (InterruptedException e) {e.printStackTrace();}}public void printC() {try {for (int i = 0; i < 10; i++) {semC.acquire();System.out.print("C");semA.release();}} catch (InterruptedException e) {e.printStackTrace();}}}