2012-02-07 5 views
0

Runnablesをスケジュールし、同じスレッドから順番に実行したいが、指定されたタイムアウトの後ではない。それを行う標準的な方法はありますか?ここ 指定されたタイムアウト後に1つのスレッドから複数のRunnableを実行する

は私のコードです:それは run()をだで

public class DelayedExecutor { 
    private final long   _timeout; 
    private final List<Runnable> _tasks = new LinkedList<>(); 
    private final ThreadFactory _factory; 
    private final Thread   _supervisor; 

    public DelayedExecutor(long timeout, ThreadFactory factory) { 
     _timeout = timeout; 
     _factory = factory; 

     _supervisor = new Thread(new Runnable() { 
      @Override 
      public void run() { 
       while (_supervisor.isInterrupted()) { 
        try { 
         Thread.sleep(_timeout); 
        } 
        catch (InterruptedException e) { 
         if (_supervisor.isInterrupted()) 
          break; 
        } 

        synchronized (_tasks) { 
         ArrayList<Runnable> prepared = new ArrayList<>(_tasks); 
         Collections.reverse(prepared); 

         execute(prepared); 

         _tasks.clear(); 
        } 
       } 
      } 
     }); 

     _supervisor.setDaemon(true); 
     _supervisor.start(); 
    } 

    public void schedule(Runnable runnable) { 
     synchronized (_tasks) { 
      _tasks.add(runnable); 
     } 
    } 

    private void execute(final List<Runnable> tasks) { 
     _factory.newThread(new Runnable() { 
      @Override 
      public void run() { 
       for (Runnable runnable : tasks) 
        runnable.run(); 
      } 
     }); 
    } 
} 
+0

これを順番に実行したいのですか? – Kiril

+0

@Lirikはい。それ以前のタイムアウト(または他の何らかの条件)ではありません。すなわちn個の実行可能ファイルは既に待機している。 – aav

+0

それは '以前ではありません'を修正してください –

答えて

2

、私はあなたがやっているかを理解し始めていると、それは小さな変更を加えたProducer/Consumerパターンのように思えると思います。私たちのチャットに基づいて、あなたは固定料金で消費者を経営したいと思っています。これはあなたのアイデアを与える(しかし、あなたの実装で同時コレクションを使用)する必要があります

public FixedRateConsumer implements Runnable 
{ 
    private final object _lock = new object(); 
    // *** use a concurrent collection here *** 
    private Queue<Runnable> _workQueue; 

    public FixedRateConsumer() 
    { 
     _workQueue = new Queue<Runnable>(); 
    } 

    public scheduleTask(Runnable task) 
    { 
     synchronized(_lock) 
     { 
      _workQueue.put(task); 
     } 
    } 

    public void run() 
    { 
     synchronized(_lock) 
     { 
      while(_workQueue.poll()!=null) 
      { 
       _workQueue.take().run(); 
      } 
     } 
    } 
} 

をそして今、あなただけの固定レートで実行するように、消費者のスケジュールを設定する必要があります。

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); 
FixedRateConsumer consumer = new FixedRateConsumer(); 

scheduler.scheduleAtFixedRate(consumer, /*specify initial delay*/, /*specify rate*/, /*specify TimeUnit*/); 

あなたのプロデューサーができます

// Then you just schedule your tasks like this 
consumer.scheduleTask(new Runnable()); 
+0

ただし、ここに追加するべき点は、これはちょっとした反パターンだということです...あなたが特定のレートで消費者を動かすための非常に特殊な理由がない限り、このアプローチを避けることをお勧めします。一般的には、コンシューマ "フルボア"を実行し、キューからデータを消費させ、キューが空の場合(BlockingQueueを利用する)ブロックします。 – Kiril

+0

これはどの言語ですか? JavaとC#の間のクロスのようです。 :) – Tudor

+0

これはJavaとC#の間のクロスです。)... C#を終日行っていて、メモ帳で書くときに「習慣」を壊すのは難しいです。 – Kiril

0

一つの方法は、1に設定し、スレッドプールのサイズとExecutorServiceを作成し、run()方法の終わりに待つ、または眠る別Runnableを置くことであろう既に持っているRunnable間のキューに入れます。

リンクは、効果的にそれらのタスクを順番に実行するので、良い質問をしました。

+0

はい。シーケンスで実行するのに問題はありません。それはまさに私が望むものです - いくつかのRunnableの実行を遅らせて(同じスレッドから)それらをまとめて( – aav

+0

@aav)実行しますが、コメントセクションではそれらを順番に実行したいと言っています。それは並行/並列です。同じスレッドから実行することもどちらも並列ではありません。 :)それで、それは何ですか?シーケンシャルまたはパラレル実行? – Kiril

+0

@Lirik同じスレッドから相次いで1つずつ – aav

1

あなたの最善の策はScheduledThreadExecutorです。あなたは一つのスレッドのプールでそれを作成することができます。

ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1); 

その後schedulescheduleAtFixedRate方法を見てください。

+0

私が正しく理解していれば、ScheduledThreadExecutorは単一の実行可能ファイルの実行を遅らせることができます。私がしたいのは、いくつかを集めて一緒に実行することです。 – aav

+0

@aav:必要な数だけスケジュールすることができます。 – Tudor

+0

ScheduledThreadPoolExecutorはできるだけ早くRunnablesを実行します。 – aav

0

これらをすべて順番にではなく一度に実行する場合は、CountDownLatchが役立ちます。いくつかのハラハラドキドキのコメントの後

int threads = 10; 
final CountDownLatch ready = new CountDownLatch(threads); 
final CountDownLatch start = new CountDownLatch(1); 
ExecutorService executorService = Executors.newFixedThreadPool(threads); 
for(int i=1; i<=threads; i++) { 
    executorService.execute(new Runnable() { 
    public void run() { 
    ready.countDown(); //Signal that this runnable is ready 
    try { 
     start.await(); //Wait for the signal 
    } catch(InterupptedException e) {} 
    Target target = new Target(); 
    target.doSomeStuff(); 
    } 
    }); 
} 
try { 
ready.await(); //Wait till all are ready 
} catch (InterruptedException e) { 
      e.printStackTrace(); 
} 
start.countDown(); //And off they go 
関連する問題