■ CountDownLatch
そもそも Latch (ラッチ) とは?
* 以下の関連記事を参照のことhttps://blogs.yahoo.co.jp/dk521123/37076571.html
CountDownLatchについて
* スレッドを待機させることができる * 特定の条件が満たされるまですべてのスレッドを保留し、 その条件が満たされると、すべてのスレッドを同時に解放
使いどころ
* 非同期で待ち合わせる処理 例えば、以下に書いてあるような「2つのサービスに接続済みである必要があり、サービスへの接続を待機する場合」http://yuki312.blogspot.jp/2012/03/androidcountdownlatch.html
■ 主なメソッド
https://docs.oracle.com/javase/jp/6/api/java/util/concurrent/CountDownLatch.htmlawait()
=> スレッドで割り込みが発生しないかぎり、ラッチのカウントダウンがゼロになるまで 現在のスレッドを待機させる。 * 2種類ある [1] public void await() [2] public boolean await(long timeout, TimeUnit unit) パラメータ: + timeout - 待機する最長時間 + unit - timeout 引数の時間単位 戻り値: + true : カウントがゼロに達した場合 + false : カウントがゼロに達する前に待機時間が経過した場合
countDown()
=> ラッチのカウントを減算し、カウントがゼロに達すると待機中のスレッドをすべて解放する【構文】(finally句に書く方がいい)
SampleMethod(CountDownLatch countDownLatch) { try { // 処理 } catch (Exception ex) { ex.printStackTrace(); } finally { countDownLatch.countDown(); }
getCount()
=> 現在のカウントを返す
■ サンプル
Main.java
import java.util.Calendar; import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; public class Main { private static final Class<?>[] SERVICE_CLASSES = new Class<?>[] { SampleServiceA.class, SampleServiceB.class }; public static void main(String[] args) throws InterruptedException, ExecutionException { System.out.println(Calendar.getInstance().getTime().toString() + " START"); CountDownLatch countDownLatch = new CountDownLatch(SERVICE_CLASSES.length); System.out.println(Calendar.getInstance().getTime().toString() + " Create SampleServiceA"); SampleServiceA sampleServiceA = new SampleServiceA(countDownLatch); System.out.println(Calendar.getInstance().getTime().toString() + " Create SampleServiceB"); SampleServiceB sampleServiceB = new SampleServiceB(countDownLatch); System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceA.run()"); sampleServiceA.start(); System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceB.run()"); sampleServiceB.start(); System.out.println(Calendar.getInstance().getTime().toString() + " countDownLatch.await() call"); countDownLatch.await(); System.out.println(Calendar.getInstance().getTime().toString() + " END"); } }
SampleServiceA.java
import java.util.Calendar; import java.util.concurrent.CountDownLatch; public class SampleServiceA extends Thread { private CountDownLatch countDownLatch; SampleServiceA(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceA.call() START"); long sleepTime = (long)(5000L * (Math.random() * 9 + 1)); try { System.out.println("SampleServiceA.sleepTime = " + sleepTime); System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceA.Sleeping ... "); Thread.sleep(sleepTime); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println(Calendar.getInstance().getTime().toString() + " Before calling countDown " + this.countDownLatch.getCount()); this.countDownLatch.countDown(); System.out.println(Calendar.getInstance().getTime().toString() + " After calling countDown " + this.countDownLatch.getCount()); } System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceA.call() END"); } }
SampleServiceB.java
import java.util.Calendar; import java.util.concurrent.CountDownLatch; public class SampleServiceB extends Thread { private CountDownLatch countDownLatch; SampleServiceB(CountDownLatch countDownLatch) { this.countDownLatch = countDownLatch; } @Override public void run() { System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceB.call() START"); long sleepTime = (long)(5000L * (Math.random() * 9 + 1)); try { System.out.println("SampleServiceB.sleepTime = " + sleepTime); System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceB.Sleeping ... "); Thread.sleep(sleepTime); } catch (Exception ex) { ex.printStackTrace(); } finally { System.out.println(Calendar.getInstance().getTime().toString() + " Before calling countDown " + this.countDownLatch.getCount()); this.countDownLatch.countDown(); System.out.println(Calendar.getInstance().getTime().toString() + " After calling countDown " + this.countDownLatch.getCount()); } System.out.println(Calendar.getInstance().getTime().toString() + " SampleServiceB.call() END"); } }出力結果
Thu Nov 20 17:24:53 JST 2014 START Thu Nov 20 17:24:54 JST 2014 Create SampleServiceA Thu Nov 20 17:24:54 JST 2014 Create SampleServiceB Thu Nov 20 17:24:54 JST 2014 SampleServiceA.run() Thu Nov 20 17:24:54 JST 2014 SampleServiceB.run() Thu Nov 20 17:24:54 JST 2014 SampleServiceA.call() START Thu Nov 20 17:24:54 JST 2014 countDownLatch.await() call SampleServiceA.sleepTime = 5364 Thu Nov 20 17:24:54 JST 2014 SampleServiceA.Sleeping ... Thu Nov 20 17:24:54 JST 2014 SampleServiceB.call() START SampleServiceB.sleepTime = 46454 Thu Nov 20 17:24:54 JST 2014 SampleServiceB.Sleeping ... Thu Nov 20 17:24:59 JST 2014 Before calling countDown 2 Thu Nov 20 17:24:59 JST 2014 After calling countDown 1 Thu Nov 20 17:24:59 JST 2014 SampleServiceA.call() END Thu Nov 20 17:25:40 JST 2014 Before calling countDown 1 Thu Nov 20 17:25:40 JST 2014 END // ★注目★ countDown()でカウント0になって即Mainスレッドに戻る () Thu Nov 20 17:25:40 JST 2014 After calling countDown 0 Thu Nov 20 17:25:40 JST 2014 SampleServiceB.call() END
参考文献
API仕様
http://docs.oracle.com/javase/jp/7/api/java/util/concurrent/CountDownLatch.html実用例
* 今後ものすごく参考になりそうなサンプルhttp://www.insuite.jp/blog/archives/74
http://www.eeb.co.jp/wordpress/?p=279
サンプル
http://argius.hatenablog.jp/entry/20131226/1388068061http://d.hatena.ne.jp/AWAWA/20080424/1209020980
http://yuki312.blogspot.jp/2012/03/androidcountdownlatch.html
http://www.ibm.com/developerworks/jp/java/library/j-5things5.html
http://tutorials.jenkov.com/java-util-concurrent/countdownlatch.html
* テストに応用
http://wavetalker.blog134.fc2.com/blog-entry-68.html
関連記事
java.util.concurrent
java.util.concurrent についてhttp://blogs.yahoo.co.jp/dk521123/32538961.html
CountDownLatch ~カウントダウンラッチ~
http://blogs.yahoo.co.jp/dk521123/33538428.html
ExecutorService / Runnableインタフェース
http://blogs.yahoo.co.jp/dk521123/33665815.html
ScheduledExecutorService ~スケジューラ~
http://blogs.yahoo.co.jp/dk521123/33934102.html
ExecutorService / Callable / Future インタフェース
http://blogs.yahoo.co.jp/dk521123/34213161.html
タイマー
''' TaskTimer ===http://blogs.yahoo.co.jp/dk521123/33926465.html
その他
コールバック関数を自作で実装する* コールバック関数で自作可能。http://blogs.yahoo.co.jp/dk521123/34242678.html
【非同期】非同期・スレッドに関する用語
https://blogs.yahoo.co.jp/dk521123/37076571.html