有线程A,B,C,C 要等A和B都执行完了才执行,怎么实现?
LockSupport + AtomicInteger
先执行线程C,用 park() 挂起线程C,线程A、B各自执行完成时,flag 减1并判断是否为0,若为0则用unpark(c)给线程C颁发许可。
- LockSupport.park() 函数表示挂起当前线程
- LockSupport.unpark(c) 函数表示解除线程c的阻塞状态
- AtomicInteger.decrementAndGet() 函数表示将该变量减一,并返回当前变量值(线程安全的原子类)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public static void main(String[] args) {
AtomicInteger flag = new AtomicInteger(2);
Thread c = new Thread(()->{ System.out.println("线程C开启,等待线程A、B执行完成才继续执行"); LockSupport.park(); System.out.println("线程C开始执行"); }); c.start();
new Thread(()->{ System.out.println("线程A开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程A执行完成"); if (flag.decrementAndGet() == 0){ LockSupport.unpark(c); } }).start(); new Thread(()->{ System.out.println("线程B开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("线程B执行完成"); if (flag.decrementAndGet() == 0){ LockSupport.unpark(c); } }).start(); }
|
CountDownLatch
CountDownLatch 有一个计数器,countDown() 方法对计数器做减操作,await 方法等待计数器达到0。所有await的线程都会阻塞直到计数器为0或者等待线程中断或者超时.
- latch.countDown() 函数将计数器减一
- latch.await() 函数表示,当计数器为0时才接着往下执行,否则陷入阻塞
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(2);
new Thread(() -> { System.out.println("线程A开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程A执行完成"); }).start();
new Thread(() -> { System.out.println("线程B开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); latch.countDown(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程B执行完成");
}).start();
new Thread(() -> { System.out.println("线程C开启,等待线程A、B执行完成才继续执行"); try { latch.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程C执行完成");
}).start();
}
|
CyclicBarrier
CyclicBarrier 与 CountDownLatch 类似 ,它能阻塞一组线程全部到某个状态再同时执行。 CyclicBarrier 与 CountDownLatch 的关键区别在于,所有的线程必须全部到达位置,才能继续执行。 CountDownLatch 用于等待事件,而 CyclicBarrier 用于等待其他线程,在任意一个线程没有完成之前,所有线程都不能继续执行。
- barrier.await() 函数使当前线程阻塞,直到相应数量的线程都执行到了该函数,才会将所有线程解锁,往下执行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3);
new Thread(() -> { System.out.println("线程A开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); System.out.println("线程A执行完成,等待其它线程一起冲破栅栏"); barrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程A执行完成"); }).start();
new Thread(() -> { System.out.println("线程B开始执行"); try { TimeUnit.SECONDS.sleep(new Random().nextInt(10)); System.out.println("线程B执行完成,等待其它线程一起冲破栅栏"); barrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程B执行完成");
}).start();
new Thread(() -> { try { System.out.println("线程C开启,等待线程AB执行完成一起冲破栅栏"); barrier.await(); } catch (Exception e) { e.printStackTrace(); } System.out.println("线程C执行完成");
}).start();
}
|