文章目录
- 前言
- 三种方案
- 1.利用join
- 2.利用线程计数器CountDownLatch
- 3.利用park实现
- 总结
前言
多任务执行的时候,有时候有这样的场景,就是有三个事件 ABC,AB执行顺序无所谓,但是C一定要在AB执行之后,再执行;
例如: 计算 1+ 2 =3;
先获取1 和 2 的顺序无所谓,可以并行
但是计算等于3的时候,一定要在 1 2 之后;
三种方案
1.利用join
多线程执行的情况下, join 可以保证一个线程执行完;
代码如下(示例):
public class AB并行后Join执行C {
@SneakyThrows
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread a = new Thread(() -> {
System.out.println("A");
});
a.start();
Thread b = new Thread(() -> {
System.out.println("B");
});
b.start();
a.join();
b.join();
new Thread(() -> {
System.out.println("C");
}).start();
}
}
}
2.利用线程计数器CountDownLatch
多线程执行下,计数器可以保证多线程之间的信息同步;
public class AB并行后执行C {
public static void main(String[] args) {
CountDownLatch countDownLatch = new CountDownLatch(2);
new Thread(() -> {
System.out.println("A");
countDownLatch.countDown();
}).start();
new Thread(() -> {
System.out.println("B");
countDownLatch.countDown();
}).start();
new Thread(() -> {
try {
countDownLatch.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
System.out.println("C");
}).start();
}
}
3.利用park实现
LockSupport中的park() 和unpark()可以实现上述场景,但是需要借助计数器,这里使用原子类实现;
public class AB并行后park执行C {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
AtomicInteger atomicInteger = new AtomicInteger(2);
Thread c = new Thread(() -> {
LockSupport.park();
System.out.println("C");
});
c.start();
new Thread(() -> {
System.out.println("A");
while (atomicInteger.decrementAndGet() == 0) {
LockSupport.unpark(c);
}
}).start();
new Thread(() -> {
System.out.println("B");
while (atomicInteger.decrementAndGet() == 0) {
LockSupport.unpark(c);
}
}).start();
}
}
}
总结
其实这里实现的方案大同小异,但是比较推荐后两种;
思路都是通过线程之间通信,完成并行之后的串行;