14

ScheduledExecutorService前のタスクがまだ終了していない場合、タスクの複数のスレッドを生成するために使用することに興味があります。たとえば、0.5 秒ごとにファイルを処理する必要があります。最初のタスクがファイルの処理を開始し、最初のスレッドが終了していない場合は 0.5 秒後に 2 番目のスレッドが生成され、2 番目のファイルの処理が開始されます。これは、次のような方法で実行できます。

    ScheduledExecutorService executor = Executors.newScheduledThreadPool(4)
    while (!executor.isShutdown()) {  
        executor.execute(task);
        try {
            Thread.sleep(500);
        } catch (InterruptedException e) {
            // handle
        }
    }

今私の質問:なぜ私はそれを行うことができないのexecutor.scheduleAtFixedRateですか?

私が得るのは、最初のタスクに時間がかかる場合、最初のタスクが終了するとすぐに2番目のタスクが開始されますが、エグゼキューターにスレッドのプールがあっても新しいスレッドは開始されません。executor.scheduleWithFixedDelay明確です - タスクは同じ時間間隔で実行され、タスクを完了するのにどれだけ時間がかかるかは問題ではありません。ScheduledExecutorServiceだから多分私は目的を誤解しました。

多分私は別の種類のエグゼキューターを見るべきですか?または、ここに投稿したコードを使用するだけですか? 何かご意見は?

4

2 に答える 2

11

スケジュールされた実行ごとにネストされた匿名ランナブルを起動することで問題を解決しました。

final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE);

final Runnable command = new SlowRunnable();

service.scheduleAtFixedRate(
    new Runnable() {
      @Override
      public void run() {
        service.execute(command);
      }
    }, 0, 1, TimeUnit.SECONDS);

この例では、間隔ごとに高速命令を実行する 1 つのスレッドが存在するため、次の間隔が満了したときに確実に終了します。残りの POOL_SIZE-1 スレッドは、SlowRunnable の run() を並行して実行します。これには、単一の間隔の期間よりも長い時間がかかる場合があります。

コードを最小限に抑え、同じ ScheduledExecutorService を再利用するこのソリューションは気に入っていますが、適切なサイズにする必要があり、すべてのコンテキストで使用できるとは限らないことに注意してください。スケジュールされたタスクを時間内に実行するスレッドがないこと。

また、間隔を 1 TimeUnit.NANOSECONDS に設定すると、メインのランナブルの実行も遅くなりすぎる可能性があります。

于 2016-09-06T13:07:51.240 に答える
0

scheduleAtFixedRateメソッドの 1 つが探しているものです。前のタスクが終了していなくても、指定された間隔でプールからスレッド内のタスクを開始します。処理を行うためのスレッドが不足している場合は、ThreadPoolExecutor のドキュメントで説明されているように、プール サイズの制約を調整してください。

于 2011-07-27T19:43:27.960 に答える