假设有这样一个场景,有一个任务有100个步骤。希望用两个线程进行接力完成。也就是第一个步骤是线程1
去做,做完了,通知线程2
去做第二个任务;线程2
做完第二个任务了,再通知线程1
去做第三个任务。以此类推,直到完成全部的任务。
(没想到有什么实际场景需要这样做~)
实现思路是这样的:
- 首先让一个线程先去搞步骤1,搞完了,就阻塞,通知第二个线程
- 第二个线程接到通知就开始搞自己的,搞完了,通知对方,然后阻塞自己。
- 以此类推
代码上打算用 wait + notify 去实现。这里有一个前提就是 notify 是无害的,也就是可以无限次调用。
public class Client {
public static final Class<Client> sLock = Client.class;
public static void main(String[] args) throws InterruptedException {
System.out.println("main...");
synchronized (sLock) {
// notify 无副作用,没有被阻塞的线程也可以随便调用!
sLock.notify();
sLock.notify();
}
Thread.sleep(10); // 保证上面的 notify 不影响到下面的逻辑
one2();
}
private static void one2() {
Client client = new Client();
new Thread(() -> {
reduce(client);
}, "cat").start();
new Thread(() -> {
reduce(client);
}, "BANANA").start();
}
private static void reduce(Client client) {
try {
synchronized (sLock) {
while (client.rest > 0) {
sLock.notify();
client.rest--;
System.out.println(Thread.currentThread()
+ " $ " + (client.rest + 1));
sLock.wait();
}
sLock.notify();
System.out.println("notify ");
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static final int SIZE = 100;
private int rest = SIZE;
}
输出效果:
main...
Thread[cat,5,main] $ 100
Thread[BANANA,5,main] $ 99
。。。
Thread[BANANA,5,main] $ 7
Thread[cat,5,main] $ 6
Thread[BANANA,5,main] $ 5
Thread[cat,5,main] $ 4
Thread[BANANA,5,main] $ 3
Thread[cat,5,main] $ 2
Thread[BANANA,5,main] $ 1
notify
notify