2017-11-23 6 views
0

CountDownLatchを使用して、N個の操作が完了するのを待ってからコードを実行しますが、N回の操作がすべて完了していなくても最終コードが実行されるようにタイムアウトします。 すなわち:CountDownLatch with dynamic timeout

CountDownLatch latch= new CountDownLatch(N); 
    latch.await(20, TimeUnit.MINUTES); 
    //Some code 

私はそれはラッチがカウントダウンを取得するたびにリセットされているように、動的にする20分のタイムアウトをしたいと思いますので、ラッチがインクルードが20分を最後に経過している場合にのみ、お待ちしており終了しますそれはカウントダウン(またはNカウントダウンを受け取ったときの通常のケース)です。これはどんな方法でもサポートされていますか?

答えて

0

この機能は、ご自身のCountDownLatchで実装できます。メソッドcountDown()が呼び出されたときのタイムスタンプを保持し、待機が開始されたときのタイムスタンプと比較して待機時間を調整し、タイムスタンプが異なる場合は再び待機することができます。

import java.time.LocalTime; 
import java.util.Arrays; 
import java.util.List; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.TimeUnit; 

public class Test { 

    public static void main(String[] args) throws InterruptedException { 

     MyCountDownLatch latch = new MyCountDownLatch(3); 

     // Create three workers and give them different work time 
     Worker worker1 = new Worker("A", 1, latch); 
     Worker worker2 = new Worker("B", 3, latch); 
     Worker worker3 = new Worker("C", 5, latch); 
     List<Worker> workers = Arrays.asList(worker1, worker2, worker3); 

     // Start the workers 
     workers.forEach(Worker::start); 

     // Wait until the latch to count down to zero, or no countdown in 
     // 3 seconds. 
     boolean result = latch.waitFor(3, TimeUnit.SECONDS); 
     System.out.printf("%s | latch.waitFor() returns %b\n", LocalTime.now(), result); 

     // Terminate those workers who are still running 
     workers.stream().filter(Worker::isAlive).forEach(Worker::interrupt); 
    } 


    static class Worker extends Thread { 
     private String name; 
     private int workTime; 
     private CountDownLatch latch; 

     public Worker(String name, int workTime, CountDownLatch latch) { 
      this.name = name; 
      this.workTime = workTime; 
      this.latch = latch; 
     } 

     @Override 
     public void run() { 
      try { 
       System.out.printf("%s | Worker %s started\n", LocalTime.now(), name); 
       Thread.sleep(workTime * 1000L); 
       System.out.printf("%s | Worker %s finished\n", LocalTime.now(), name); 
      } catch (InterruptedException e) { 
       System.out.printf("%s | Worker %s interrupted\n", LocalTime.now(), name); 
      } finally { 
       latch.countDown(); 
      } 
     } 
    } 
} 
:たとえば、ここに

import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.TimeUnit; 
import java.util.concurrent.atomic.AtomicLong; 

public class MyCountDownLatch extends CountDownLatch { 
    private AtomicLong timestamp; 

    public MyCountDownLatch(int count) { 
     super(count); 
     timestamp = new AtomicLong(System.nanoTime()); 
    } 

    @Override 
    public void countDown() { 
     super.countDown(); 
     timestamp.set(System.nanoTime()); 
    } 

    public boolean waitFor(long timeout, TimeUnit unit) throws InterruptedException { 
     long start = timestamp.get(); 
     long diff = 0; 
     for (;;) { 
      boolean result = await(unit.toNanos(timeout) - diff, TimeUnit.NANOSECONDS); 
      if (timestamp.get() == start) return result; 
      start = timestamp.get(); 
      diff = System.nanoTime() - start; 
     } 
    } 
} 

そして、テストプログラムであります