7

によって実行される一連のタスク (つまりRunnables) がありExecutorます。
各タスクを続行するには、特定の条件が有効である必要があります。Executorタスクをキューの最後に移動し、後で条件が有効になり、タスクを実行して終了できるようになったときにそれらを実行するように構成する方法があるかどうかを知りたいと思います。
したがって、動作は次のようになります。

  1. Thread-1キューからタスクを取得し、run呼び出されます
  2. 内部runの条件はまだ有効ではありません
  3. タスクが停止し、Thread-1タスクをキューの最後に配置して、実行する次のタスクを取得します
  4. 後でThread-X(スレッドプールから) キュー条件からタスクを再度選択し、タスクが実行されている状態が有効です
4

3 に答える 3

3

忙しく待機する必要がない限り、実行が「有効」になった後にキャンセルまたは強制終了する適切なポーリング間隔で、ScheduledExecutorService に繰り返しタスクを追加できます。

ScheduleExecutorService ses = ...

ses.scheduleAtFixedRate(new Runnable() {
    public void run() {
        if (!isValid()) return;
        preformTask();
        throw new RuntimeException("Last run");
    }
}, PERIOD, PERIOD, TimeUnit.MILLI_SECONDS);
于 2012-11-20T21:41:42.807 に答える
3

最初にエグゼキュータを作成します。

いくつかの可能性があります。

あなたのタスクがステータスを照会するための単純なインターフェース(「NeedReschedule」または「Completed」の列挙型のようなもの)を実装するとRunnable仮定すると、タスクとエグゼキューターをインスタンス化パラメーターとして受け取るタスクのラッパー(実装)を実装します. このラッパーは、バインドされているタスクを実行し、後でそのステータスを確認し、必要に応じて、終了する前にエグゼキューターで自身のコピーを再スケジュールします。

または、実行メカニズムを使用して、タスクを再スケジュールする必要があることをラッパーに通知することもできます。このソリューションは、タスクに特定のインターフェイスを必要としないという意味でより単純であるため、単純なRunnableものを問題なくシステムに投入できます。ただし、例外により計算時間が長くなります (オブジェクトの構築、スタック トレースなど)。

例外シグナル伝達メカニズムを使用したラッパーの可能な実装を次に示します。ラップされた runnable によって起動される可能性があるRescheduleExceptionクラス extendsを実装する必要があります (このセットアップでは、タスク用のより具体的なインターフェイスは必要ありません)。Throwable別の回答で提案されているように単純なものを使用することもできRuntimeExceptionますが、メッセージ文字列をテストして、これが待っている例外であるかどうかを確認する必要があります。

 public class TaskWrapper implements Runnable {

    private final ExecutorService executor;
    private final Runnable task;       

    public TaskWrapper(ExecutorService e, Runnable t){
         executor = e;
         task = t;
    }

@Override
public void run() {

    try {
               task.run();
    } 
    catch (RescheduleException e) {
        executor.execute(this);
    }
}

これは、再スケジュールを要求する 200 個のラップされたタスクをランダムに起動する非常に単純なアプリケーションです。

class Task implements Runnable {

  @Override
  public void run(){
     if (Maths.random() > 0.5)
      throw new RescheduleException();
   }     
}


public class Main {

public static void main(String[] args){

    ExecutorService executor = Executors.newFixedThreadPool(10);

    int i = 200;
            while(i--)
       executor.execute(new TaskWrapper(executor, new Task());
}
}

(メッセージ キューを使用して) 他のスレッドの結果を監視し、必要に応じて再スケジュールするための専用スレッドを用意することもできますが、他のソリューションと比較して 1 つのスレッドが失われます。

于 2012-11-20T21:24:17.297 に答える
3

Java 6 では、ThreadPoolExecutorコンストラクターはBlockingQueue<Runnable>、キューに入れられたタスクを格納するために使用される を受け取ります。をオーバーライドするブロッキング キューを実装しpoll()て、「準備完了」ジョブを削除して実行しようとした場合に、poll通常どおりに処理を進めることができます。それ以外の場合、ランナブルはキューの後ろに配置され、おそらく短いタイムアウトの後、再度ポーリングを試みます。

于 2012-11-20T21:24:38.417 に答える