闭锁
闭锁作用是,在闭锁到达结束之前,会阻止其他线程通过,而到达结束的时候,则打开门,允许其余线程通过。
CountDownLatch
是一种闭锁实现,是通过计数的形式实现,可以实现一个主线程需要依赖其他多个线程完成后,再继续 执行的功能。下面是自己写的一个很简单的demo:
public static void main(String[] args) { CountDownLatch counter = new CountDownLatch(3); for (int i = 0; i < 3; i++) { Thread thread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(5000); counter.countDown(); } catch (Exception e) { counter.countDown(); } } }); thread.start(); } System.out.printf("我在等待三个线程运行完\n"); try { counter.await(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.printf("我等完了三个线程运行"); }
CyclicBarrier
就是相当于设置一道基线,当所有线程都到达这个基线的位置时候,才能继续往下走。例子如下:
public static void main(String[] args) throws Exception { // 这里Cyclic构造参数里可以传递一个Runnable,意思就是当所有线程都到达的时候,将会执行这个runnable CyclicBarrier cb = new CyclicBarrier(3, new Runnable() { @Override public void run() { System.out.printf("比赛现在开始~"); } }); Thread thread1 = new Thread(new Sports(cb, "中单")); Thread thread2 = new Thread(new Sports(cb, "上单")); Thread thread3 = new Thread(new Sports(cb, "打野")); thread1.start(); thread2.start(); thread3.start(); } public static class Sports implements Runnable { CyclicBarrier barrier = null; String name = null; Sports(CyclicBarrier cb, String name) { this.barrier = cb; this.name = name; } @Override public void run() { try { System.out.printf(name + "在准备中\n"); Thread.sleep(new Random().nextInt(10) * 1000); System.out.printf(name + "准备完毕,等待其他位置\n"); barrier.await(); } catch (Exception e) {} } }
运行结果如下:
FutureTask
FutureTask也可以用来实现闭锁的功能,因为FutureTask的是可以返回结果的,当主线程去调用futureTask.get()的时候,会返回结果,如果线程还没有执行完毕,就会一直阻塞等待,直到拿到结果为止,当然可以设置等待的超时时间。