非个人面试,这是京东面试的一道编程题
前言:这道题挺有意思的,刚好我刚学了基础的Java多线程,那就试一试。另外以下的两种方案都需要注意就是,
wait()
需要放在while
循环里以防错失notify
信号
一种代码风格比较好的方案:同步方法
package thread.print;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicPrint {
private ExecutorService executorService = Executors.newFixedThreadPool(2);
private boolean printA = true;
private synchronized void printA() throws InterruptedException {
while (!printA) wait();
System.out.println("A");
printA = false;
notifyAll();
}
private synchronized void printB() throws InterruptedException {
while (printA) wait();
System.out.println("B");
printA = true;
notifyAll();
}
private Thread a = new Thread(() -> {
while (!Thread.interrupted()) {
try {
printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
private Thread b = new Thread(() -> {
while (!Thread.interrupted()) {
try {
printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
public CyclicPrint() throws InterruptedException {
executorService.execute(a);
executorService.execute(b);
Thread.sleep(1000);
executorService.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
new CyclicPrint();
}
}
另外一种与上面大同小异的方案,但是可读性较之低一些:同步临界区
package thread.print;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class CyclicPrint2 {
private ExecutorService executorService = Executors.newFixedThreadPool(2);
private final CyclicPrint2 p = this;
private boolean printA = true;
private Thread a = new Thread(() -> {
while (!Thread.interrupted()) {
synchronized (p) {
while (!printA) {
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("A");
printA = false;
p.notifyAll();
}
}
});
private Thread b = new Thread(() -> {
while (!Thread.interrupted()) {
synchronized (p) {
while (printA) {
try {
p.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("B");
printA = true;
p.notifyAll();
}
}
});
public CyclicPrint2() throws InterruptedException {
executorService.execute(a);
executorService.execute(b);
Thread.sleep(1000);
executorService.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
new CyclicPrint();
}
}
Lock
+Condition
版
package thread.print;
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 CyclicPrint3 {
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
private ExecutorService executorService = Executors.newFixedThreadPool(2);
private boolean printA = true;
private void printA() throws InterruptedException {
lock.lock();
while (!printA) condition.await();
System.out.println("A");
printA = false;
condition.signalAll();
lock.unlock();
}
private void printB() throws InterruptedException {
lock.lock();
while (printA) condition.await();
System.out.println("B");
printA = true;
condition.signalAll();
lock.unlock();
}
private Thread a = new Thread(() -> {
while (!Thread.interrupted()) {
try {
printA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
private Thread b = new Thread(() -> {
while (!Thread.interrupted()) {
try {
printB();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
public CyclicPrint3() throws InterruptedException {
executorService.execute(a);
executorService.execute(b);
Thread.sleep(1000);
executorService.shutdownNow();
}
public static void main(String[] args) throws InterruptedException {
new CyclicPrint3();
}
}
结语:使用同步+循环条件的解决方案效果还不错。