今日复习来自极海Channel的一个面试
如何实现两个线程实现交替打印,线程A打印A,线程B打印B?
讲真当时看到的时候,脑子里面第一反应就是信号量和synchronized解法,那有synchronized就会有ReentrantLock,那就尝试用这三个解法回答一下吧。
代码地址:线程交替打印
1、synchronized实现
synchronized的方式实现主要是进行加锁,通过一把对象锁,在代码块内只允许一个线程执行后续操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| Object lock = new Object();
Thread threadA = new Thread(new SynchronizedPrintThread(lock, "A", 0), "线程A"); Thread threadB = new Thread(new SynchronizedPrintThread(lock, "B",1), "线程B"); Thread threadC = new Thread(new SynchronizedPrintThread(lock, "C",2), "线程C");
threadA.start(); threadB.start(); threadC.start();
class SynchronizedPrintThread implements Runnable { private final Object lock; private final String message; private final int order; private static int currentOrder = 0;
public SynchronizedPrintThread(Object lock, String message, int order) { this.lock = lock; this.message = message; this.order = order; }
@Override public void run() { try { synchronized (lock) { for (int i = 0; i < 10; i++) { while (currentOrder % 3 != order) { lock.wait(); } System.out.println(Thread.currentThread().getName() + "------" + message); currentOrder++; lock.notifyAll(); } } } catch (InterruptedException e) { e.printStackTrace(); } } }
|
2、ReentrantLock实现
ReentrantLock实现,同样会传入锁,但是lock和unlock是自己规定,所以当需要判断打印的时候,进行加锁操作,同时每个线程进去之后判断是否是自己需要打印,如果不是,那么就唤醒下一个线程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| ReentrantLock lock = new ReentrantLock();
Condition conditionA = lock.newCondition(); Condition conditionB = lock.newCondition(); Condition conditionC = lock.newCondition();
Thread threadA = new Thread(new ReentrantLockPrintThread(lock, conditionA, conditionB, "A", 0)); Thread threadB = new Thread(new ReentrantLockPrintThread(lock, conditionB, conditionC, "B", 1)); Thread threadC = new Thread(new ReentrantLockPrintThread(lock, conditionC, conditionA, "C", 2));
threadA.start(); threadB.start(); threadC.start();
class ReentrantLockPrintThread implements Runnable { private final Lock lock; private final Condition current; private final Condition next; private final String message; private final int order;
private static int currentOrder = 0;
public ReentrantLockPrintThread(Lock lock, Condition currentCondition, Condition nextCondition, String message, int order) { this.lock = lock; this.current = currentCondition; this.next = nextCondition; this.message = message; this.order = order; }
@Override public void run() { try { for (int i = 0; i < 10; i++) { lock.lock(); while (currentOrder % 3 != order) { current.await(); } System.out.println(Thread.currentThread().getName() + "------" + message); currentOrder++; next.signal(); lock.unlock(); } } catch (InterruptedException e) { e.printStackTrace(); } } }
|
注意:Condition对象是与锁(ReentrantLock)关联的条件对象,用于线程间的等待和通知机制。因此锁的类型不并不是Object
1 2 3 4 5
| ReentrantLock lock = new ReentrantLock();
lock.newContional(); lock.newContional(); lock.newContional();
|
3、信号量实现
在使用信号量实现的时候,需要指定谁最先拥有许可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| Semaphore semaphoreA = new Semaphore(1); Semaphore semaphoreB = new Semaphore(0); Semaphore semaphoreC = new Semaphore(0);
Thread threadA = new Thread(new SemaphorePrintThread(semaphoreA, semaphoreB, "A", 0)); Thread threadB = new Thread(new SemaphorePrintThread(semaphoreB, semaphoreC, "B", 1)); Thread threadC = new Thread(new SemaphorePrintThread(semaphoreC, semaphoreA, "C", 2));
threadA.start(); threadB.start(); threadC.start();
class SemaphorePrintThread implements Runnable { private final Semaphore current; private final Semaphore next; private static int currentOrder = 0;
private final String message; private final int order;
public SemaphorePrintThread(Semaphore current, Semaphore next, String message, int order) { this.current = current; this.next = next; this.message = message; this.order = order; }
@Override public void run() { try {
for (int i = 0; i < 10; i++) {
current.acquire(); System.out.println(Thread.currentThread().getName() + "------" + message); currentOrder++; next.release(); } } catch (Exception e) { e.printStackTrace(); } } }
|