这两天在知乎上看到不同的人都问了这个问题,回想起当年找实习的时候也写过这个问题,觉得还蛮有意思的,就在这里记录一下。
最常见的是使用 notify() wait()
public class Demo {
public static void main(String[] args) {
Object lock = new Object();
new Printer("线程 A", lock).start();
new Printer("线程 B", lock).start();
}
private static class Printer extends Thread {
private final Object lock;
public Printer(String name, Object lock) {
super(name);
this.lock = lock;
}
@Override
public void run() {
for (char i = 'A'; i <= 'Z'; i++) {
synchronized (lock) {
System.out.println(getName() + " 打印字母: " + i);
lock.notify();
try {
Thread.sleep(500);
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
不使用锁
public class Demo {
/**
* 使用计数器,两个线程分别在计数器为奇数/偶数时打印,
* 使用AtomicBoolean更简单,这里使用AtomicInteger
* 是考虑可拓展为N个线程交替打印
*/
public static void main(String[] args) {
AtomicInteger counter = new AtomicInteger(0);
new PrinterA("线程 A", counter).start();
new PrinterB("线程 B", counter).start();
}
private static class PrinterA extends Thread {
private final AtomicInteger counter;
public PrinterA(String name, AtomicInteger counter) {
super(name);
this.counter = counter;
}
@Override
public void run() {
for (char i = 'A'; i <= 'Z'; ) {
if (counter.get() % 2 == 0) {
System.out.println(getName() + " 打印字母: " + i++);
counter.incrementAndGet();
}
}
}
}
private static class PrinterB extends Thread {
private final AtomicInteger counter;
public PrinterB(String name, AtomicInteger counter) {
super(name);
this.counter = counter;
}
@Override
public void run() {
for (char i = 'A'; i <= 'Z'; ) {
if (counter.get() % 2 != 0) {
System.out.println(getName() + " 打印字母: " + i++);
counter.incrementAndGet();
}
}
}
}
}
使用 ReentrantLock
public class Demo {
public static void main(String[] args) {
ReentrantLock lock = new ReentrantLock();
Condition aPrintCondition = lock.newCondition();
Condition bPrintCondition = lock.newCondition();
Condition cPrintCondition = lock.newCondition();
new Printer("线程 A", lock, aPrintCondition, bPrintCondition).start();
new Printer("线程 B", lock, bPrintCondition, cPrintCondition).start();
new Printer("线程 C", lock, cPrintCondition, aPrintCondition).start();
}
private static class Printer extends Thread {
private final ReentrantLock lock;
private final Condition waitCondition;
private final Condition signalCondition;
public Printer(String name, ReentrantLock lock, Condition waitCondition, Condition signalCondition) {
super(name);
this.lock = lock;
this.waitCondition = waitCondition;
this.signalCondition = signalCondition;
}
@Override
public void run() {
for (char i = 'A'; i <= 'Z'; i++) {
lock.lock();
try {
System.out.println(getName() + " 打印字母: " + i);
Thread.sleep(500);
signalCondition.signal();
waitCondition.await();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}
还可以使用其他juc包里的同步类 Semaphore 等等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。