Java多線程 類庫中的構件(一)

1.CountDownLatch

  同步輔助類,在完成一組正在其他線程中執行的操作之前,它允許一個或多個線程一直等待。用給定的計數初始化CountDownLatch。由於調用了 countDown() 方法,所以在當前計數到達零之前,await 方法會一直受阻塞。之後,會釋放所有等待的線程,await 的所有後續調用都將立即返回。這種現象只出現一次——計數無法被重置。如果需要重置計數,請考慮使用 CyclicBarrier。CountDownLatch 是一個通用同步工具,它有很多用途。將計數 1 初始化的 CountDownLatch 用作一個簡單的開/關鎖存器,或入口:在通過調用 countDown() 的線程打開入口前,所有調用 await 的線程都一直在入口處等待。用 N 初始化的 CountDownLatch 可以使一個線程在 N 個線程完成某項操作之前一直等待,或者使其在某項操作完成 N 次之前一直等待。下面是一個典型的用法,主線程中等待所有的任務全部執行完畢後返回。CountDownLatch強調的是一個線程(或多個)需要等待另外的n個線程幹完某件事情之後才能繼續執行

class Driver2 { // ...
   void main() throws InterruptedException {
     CountDownLatch doneSignal = new CountDownLatch(N);
     Executor e = ...

     for (int i = 0; i < N; ++i) // create and start threads
       e.execute(new WorkerRunnable(doneSignal, i));

     doneSignal.await();           // wait for all to finish
   }
 }

 class WorkerRunnable implements Runnable {
   private final CountDownLatch doneSignal;
   private final int i;
   WorkerRunnable(CountDownLatch doneSignal, int i) {
      this.doneSignal = doneSignal;
      this.i = i;
   }
   public void run() {
      try {
        doWork(i);
        doneSignal.countDown();
      } catch (InterruptedException ex) {} // return;
   }

   void doWork() { ... }
 }
2.CyclicBarrier
  用法類似於CountDownLatch,只是CountDownLatch是隻觸發一次的時間,而CyclicBarrier可以多次重用;該類是一個同步輔助類,它允許一組線程互相等待,直到到達某個公共屏障點 (common barrier point)。在涉及一組固定大小的線程的程序中,這些線程必須不時地互相等待。CyclicBarrier 支持一個可選的 Runnable 命令,在一組線程中的最後一個線程到達之後(但在釋放所有線程之前),該命令只在每個屏障點運行一次。CyclicBarrier強調的是n個線程,大家相互等待,只要有一個沒完成,所有人都得等着
  • CyclicBarrier(int parties):創建一個新的 CyclicBarrier,它將在給定數量的參與者(線程)處於等待狀態時啓動;即在該barrier上等待的線程數量到達parties時,啓動barrier,所有線程通過柵欄繼續執行;
  • public CyclicBarrier(int parties, Runnable barrierAction):創建一個新的CyclicBarrier,它將在給定數量的參與者(線程)處於等待狀態時啓動,並在啓動 barrier 時執行給定的屏障操作,即runnable中的動作,該操作由最後一個進入 barrier 的線程執行。

  下面是簡單的一個應用:

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class Beer {

public static void main(String[] args) {
final int count = 5;
final CyclicBarrier barrier = new CyclicBarrier(count, new Runnable() {
@Override
public void run() {
System.out.println("drink beer!");
}
});

// they do not have to start at the same time...
for (int i = 0; i < count; i++) {
new Thread(new Worker(i, barrier)).start();
}
}

}

class Worker implements Runnable {
final int id;
final CyclicBarrier barrier;

public Worker(final int id, final CyclicBarrier barrier) {
this.id = id;
this.barrier = barrier;
}

@Override
public void run() {
try {
System.out.println(this.id + "starts to run !");
Thread.sleep((long) (Math.random() * 10000));
System.out.println(this.id + "arrived !");
this.barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (BrokenBarrierException e) {
e.printStackTrace();
}
}
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章