CountDownLatch実戦ガイド

5580 ワード

もっと読む
CountDownLatchはconcuurentパッケージのツールクラスであり、カウンタであり、1つ以上のスレッドが全部実行されるまで待機しています。
CountDown Latchは何ですか?
unt DownLatchはjava 1.5で導入されました。一緒に導入された同時工具類はCyclicBarrier、Semaphore、ConcerenthashMapとBlockingQueがあります。CountDownLatchというクラスは、他のスレッドがそれぞれの作業を完了するのを待ってスレッドを実行することができます。例えば、アプリケーションのメインスレッドは、フレームサービスを開始するスレッドがすべてのフレームサービスを開始した後に実行してほしい。
CountDownLatchは一つのカウンタによって実現され、カウンタの初期値はスレッドの数である。一つのスレッドが自分のタスクを完了するたびに、カウンタの値は1を減算します。カウンタ値が0に達すると、すべてのスレッドがタスクを完了したことを表し、閉塞上で待機しているスレッドがタスクを再開することができます。
CountDownLatchの疑似コードは以下の通りです。
//Main thread start
//Create CountDown Latch for N threads
//Create and start N threads
//Main thread wait on latch
//N threads complettes there task are returns
//Main thread reume execution
CountDownLatchはどうやって働きますか?
CountDownLatch.javaクラスで定義されているコンストラクタ:
1
2
//コンストラスa Count Down Latch initialized with the given count.
public void Countdown Latch(intcount){…}
コンストラクタにおけるカウント値は、実際にはロックが待つスレッドの数である。この値は一回だけ設定され、またCountDownLatchはこのカウント値を再設定するための機構を提供していません。
CountDownLatchとの最初のインタラクションは、メインスレッドが他のスレッドを待つことである。メインスレッドは、他のスレッドを起動した直後にCountDownLatch.await()メソッドを呼び出す必要があります。このようにメインスレッドの動作は、他のスレッドがそれぞれのタスクを完了するまで、この方法でブロックされます。
他のNスレッドは、それぞれのタスクを完了したCountDownLatchオブジェクトに通知する必要があるので、ロック対象を参照してください。このような通知メカニズムは、CountDown Latch.com Down()方法によって達成される。この方法を呼び出すたびに、コンストラクタで初期化されたcount値は1を減算します。したがって、Nスレッドがこの方法を起動すると、countの値は0に等しくなり、主スレッドがawait()方法によって、自分のタスクを実行することができます。
リアルタイムシステムでの使用シーン
JavaリアルタイムシステムのCountDownLatchにはどのような使用シーンがあるかを羅列してみましょう。私が羅列しているのは全部私の考え得るところです。他に可能な使い方がありましたら、メッセージに書いてください。
最大の並列性を実現する:複数のスレッドを同時に起動し、最大の並列性を実現したい場合があります。例えば、私たちは一つの例類をテストしたいです。最初のカウントが1のCountDownLatchを作成し、すべてのスレッドをこのロックで待機させると、簡単にテストができます。私たちはcountDown()方法を一回呼び出すだけで、スレッドを待っているすべてのスレッドを同時に再開して実行することができます。
実行を開始する前に、n個のスレッドがそれぞれのタスクを完了するのを待つ。例えば、アプリケーション起動クラスは、ユーザ要求を処理する前に、N個の外部システムが起動され、実行されていることを確認する。
デッドロック検出:非常に便利な使用シーンは、共有リソースにnスレッドを使ってアクセスでき、テスト段階ごとにスレッド数が異なり、デッドロックを生成しようとします。
この例では、アプリケーションの起動クラスをシミュレートしましたが、開始時にnスレッドクラスが起動し、これらのスレッドは外部システムをチェックして閉塞を通知し、起動クラスはずっと閉塞上に待機しています。すべての外部サービスを検証し、チェックしたら、クラス回復を開始して実行します。
CountDownLatch使用例
AbstractBaseRule Handler.java:このクラスはRunnableで、すべての特定の外部サービスの健康診断を担当しています。重複コードとロックの中心制御コードを削除しました。

public abstract class AbstractBaseRuleHandler implements Runnable {

	private CountDownLatch latch;
	
	private List errorList;
	
	private Long primaryId;
	
	public AbstractBaseRuleHandler(CountDownLatch latch,List errorList,Long primaryId) {
		this.latch =latch;
		this.errorList = errorList;
		this.primaryId =primaryId;
	}

	@Override
	public void run() {
		try {
			  int i = handleOpration(primaryId);
			  if(i == 0){
				  errorList.add(primaryId);
			  }
		}catch(Exception e){
			ThreadLocalLog.infoPro(AbstractBaseRuleHandler.class.getName(), "run",primaryId + ":          "+  e.getMessage(), null, null);
		}finally{
			latch.countDown();
		}
	}

	 public abstract int handleOpration(Long id);
}
TemplateRule DelBean.javaというクラスはAbstractBaseRule Handlerを継承して、handleation()方法を実現しました。

public class TemplateRuleDelBean extends AbstractBaseRuleHandler{

	
	/**
	 * @param latch
	 * @param errorList
	 * @param primaryId
	 */
	public TemplateRuleDelBean(CountDownLatch latch, List errorList, Long primaryId) {
		super(latch, errorList, primaryId);
	}
	
	@Override
	public int handleOpration(Long id) {
	return 0;//ruleBaseConfigEntityMapper.updateByPrimaryKeySelective(entity);
     //       ,      0
	}

}
Tempate DelSingleton.javaというクラスはメイン起動クラスで、初期化のための閉塞を担当しています。その後、すべてのサービスが検出されるまで待ちます。

public class TempateDelSingleton {

	private TempateDelSingleton() {
	}
	
	private static class TemplateInner{
		private static final TempateDelSingleton incetance = new TempateDelSingleton();
	}
	
	public static TempateDelSingleton getIncetance(){
		return TemplateInner.incetance;
	}
	
	public List handleMain(List primaryList){
		CountDownLatch _latch= new CountDownLatch(primaryList.size());
		List errorList = new ArrayList<>();
		List baseList = new ArrayList<>();
		for(Long ab : primaryList){
			baseList.add(new TemplateRuleDelBean(_latch, errorList, ab));
		}
		ExecutorService executor = Executors.newFixedThreadPool(baseList.size());
		for(final AbstractBaseRuleHandler v :  baseList){
			executor.execute(v);
		}
		 try {
			_latch.await();
		} catch (InterruptedException e) {
		}finally{			
			executor.shutdown();
		}
		return errorList;
	}
	

}
最後にメールでこの一例を走るとロックの機能を確認できます。
	public static void main(String[] args) {
		List primaryList = Arrays.asList(1l,2l,3l);
		TempateDelSingleton.getIncetance().handleMain(primaryList);
	}
出力結果:
1
3
2
いくつかの他のCountDownLatch関連の問題:
CountDown Latchの概念を説明してください。
CountDown LatchとCyclicBarrierの違いは何ですか?
いくつかのCountDownLatchの使用例を示しますか?
CountDownLatch類の中で主要な方法は何ですか?