youyichannel

志于道,据于德,依于仁,游于艺!

0%

Atomic原子操作类02

业务场景:两条线程分别计算 (3 * 5)(10 + 2)的结果,结果计算完成后,将两个结果相加。

使用CountDownLatch

public class CountDownLatchTest {
static CountDownLatch cd = new CountDownLatch(2);
static int[] arr = new int[2];

public static void main(String[] args) throws InterruptedException {
Thread A = new Thread(() -> {
arr[0] = 3 * 5;
cd.countDown();
});

Thread B = new Thread(() -> {
arr[1] = 10 + 2;
cd.countDown();
});
A.start();
B.start();
cd.await();
System.out.println(arr[0] + arr[1]);
}
}

使用CyclicBarrier

public class CyclicBarrierTest {

static CyclicBarrier cb = new CyclicBarrier(3);
static int[] arr = new int[2];

public static void main(String[] args) throws BrokenBarrierException, InterruptedException {
Thread A = new Thread(() -> {
arr[0] = 3 * 5;
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});

Thread B = new Thread(() -> {
arr[1] = 10 + 2;
try {
cb.await();
} catch (InterruptedException | BrokenBarrierException e) {
throw new RuntimeException(e);
}
});

A.start();
B.start();

cb.await();

System.out.println(arr[0] + arr[1]);
}
}

对于这个场景来说,建议使用CountDownLatch。因为CountDownLatch初始化参数直接写的是2,就是进行2次倒计时,main函数调用的await,就是告诉main线程在等待其他两个线程执行完毕。

然而,对于CyclicBarrier 实现形式,main函数和其他两个线程都被阻塞到了一个地方。此处main函数到达了屏障之后,挂起自己,等待其他两个线程达到屏障之后才开始执行。

=> 总结

  • CountDownLatch针对业务完成后执行,类似于赛跑过程中的到达终点
  • CyclicBarrier针对的是所有的线程在统一的屏障集合后开始,类似于赛跑过程中的起跑线

除此之外,CyclicBarrier支持一个Runnable的Action去做后续的数据操作,能够适用于更加复杂的场景。

/**
* Creates a new {@code CyclicBarrier} that will trip when the
* given number of parties (threads) are waiting upon it, and which
* will execute the given barrier action when the barrier is tripped,
* performed by the last thread entering the barrier.
*
* @param parties the number of threads that must invoke {@link #await}
* before the barrier is tripped
* @param barrierAction the command to execute when the barrier is
* tripped, or {@code null} if there is no action
* @throws IllegalArgumentException if {@code parties} is less than 1
*/
public CyclicBarrier(int parties, Runnable barrierAction) {
if (parties <= 0) throw new IllegalArgumentException();
this.parties = parties;
this.count = parties;
this.barrierCommand = barrierAction;
}