这是一道常见的面试题,如果遇到需要手写代码这种题,首先是要理清思路,再就是尽量体现出代码风格,关键次是顺序,
一、基于Semaphore
二、基于Synchronized
三、基于ReentrantLock
下面代码是用Semaphore的实现方式。
public static void main(String[] args) throws InterruptedException {
Semaphore a = new Semaphore(1);
Semaphore b = new Semaphore(0);
Semaphore c = new Semaphore(0);
ExecutorService poolService = Executors.newFixedThreadPool(3);
Integer count = 10;
poolService.execute(new Worker(a, b, "A", count));
poolService.execute(new Worker(b, c, "B", count));
poolService.execute(new Worker(c, a, "C", count));
Thread.sleep(1000);
poolService.shutdownNow();
}
public static class Worker implements Runnable {
private String key;
private Semaphore current;
private Semaphore next;
private Integer count;
public Worker(Semaphore current, Semaphore next, String key, Integer count) {
this.current = current;
this.next = next;
this.key = key;
this.count = count;
}
public void run() {
for(int i = 0; i < count; i++) {
try {
//获取当前的锁
current.acquire(); //current - 1
System.out.println(i+","+key);
//释放next的锁
next.release(); //next + 1
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
下面是Synchronized的实现
private static volatile Integer state = new Integer(1);
public static void main(String[] args) throws InterruptedException {
ExecutorService poolService = Executors.newFixedThreadPool(3);
Integer count = 10;
Object lock = new Object();
poolService.execute(new Worker("A", count, lock));
poolService.execute(new Worker("B", count, lock));
poolService.execute(new Worker("C", count, lock));
Thread.sleep(1000);
poolService.shutdownNow();
}
public static class Worker implements Runnable {
private String key;
private Integer count;
private Object lock;
public Worker(String key, Integer count, Object lock) {
this.key = key;
this.count = count;
this.lock = lock;
}
public void run() {
for(int i = 0; i < count; i++) {
if(key == "A") {
synchronized (lock) {
while (state != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+","+key);
state = 2;
lock.notifyAll();
}
} else if(key == "B") {
synchronized (lock) {
while (state != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+","+key);
state = 3;
lock.notifyAll();
}
} else if (key == "C") {
synchronized (lock) {
while (state != 3) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+","+key);
state = 1;
lock.notifyAll();
}
}
}
}
}
下面是基于ReentrantLock实现
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class PrintABC3 {
private static ReentrantLock lock = new ReentrantLock();
private static Condition conditionA = lock.newCondition();
private static Condition conditionB = lock.newCondition();
private static Condition conditionC = lock.newCondition();
private static volatile int state = 1;
public static void main(String[] args) throws InterruptedException {
ExecutorService poolService = Executors.newFixedThreadPool(3);
Integer count = 10;
poolService.execute(new Worker("A", count, 1, lock, conditionA, conditionB));
poolService.execute(new Worker("B", count, 2, lock, conditionB, conditionC));
poolService.execute(new Worker("C", count, 3, lock, conditionC, conditionA));
Thread.sleep(5000);
poolService.shutdownNow();
}
public static class Worker implements Runnable {
private String key;
private Integer count;
private Lock lock;
private Condition current;
private Condition next;
private int targetState;
public Worker(String key, Integer count, int targetState, Lock lock, Condition cur, Condition next) {
this.key = key;
this.count = count;
this.lock = lock;
this.current = cur;
this.next = next;
this.targetState = targetState;
}
public void run() {
this.lock.lock();
try {
for (int i = 0; i < count; i++) {
while (state != targetState) {
current.await();
}
System.out.println(i + "," + key);
state++;
if (state > 3) {
state = 1;
}
next.signal();
}
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
this.lock.unlock();
}
}
}
}