1

これが私が持っているものです... それぞれが個別に提出されるタスクのリストがありますExecutorService各タスクの実行開始後、x MS の時間制限を設けたいと考えています。Time Limit on Individual Threads に投稿されたような解決策を見たことがありますが、これはタスクが送信された時点から時間制限を設定します。

Time Limit on Individual Threadsに対する受け入れられた解決策を拡張する解決策が 1 つあると思いました。これは、スケジュールされたエグゼキュータが開始されると、キャンセル タスクをCallable別のものにラップします。これには、自明ではない方法でのから へのCallableマッピングが含まれるため、投稿して、既存の解決策を誰かが知っているかどうかを確認しようと思いました (コードの再利用は素晴らしいことであり、すべてです)。CallableFuture

ありがとう。

参考までに、 Time Limit on Individual Threads に投稿された解決策は次のとおりです。繰り返しますが、これは開始時間ではなく、送信時間からキャンセルされます。

ExecutorService service = Executors.newFixedThreadPool(N);
ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();

public <T> Future<T> executeTask(Callable<T> c, long timeoutMS){
   final Future<T> future = service.submit(c);
   canceller.schedule(new Callable<Void>(){
       public Void call(){
          future.cancel(true);
          return null;
       }
    }, timeoutMS, TimeUnit.MILLI_SECONDS);
   return future;
}
4

4 に答える 4

2

これがうまくいくかどうか見てください。

コードが乱雑で申し訳ありませんが、概念を説明するためのものです。未来をタスクに戻し、タスクに独自のタイマーを開始させます。タイマーは、タスクの開始時に開始されます。

次のコードは 10 個のタスクを追加します。それぞれの実行に 2 秒かかりますが、タイムアウトは 1 秒です。

import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class CancellableTaskDemo {
    public static void main(final String[] args) {
        new CancellableTaskDemo();
    }

    final ExecutorService ex = Executors.newFixedThreadPool(3);

    public CancellableTaskDemo() {
        for (int i = 0; i < 10; i++) {
            final int c = i;
            submitTask(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    final long t = System.currentTimeMillis();
                    try {
                        Thread.sleep(2000);
                        System.out.println("Task " + c + " done in " + (System.currentTimeMillis() - t) + "ms");
                    } catch (final InterruptedException e) {
                        System.out.println("Task " + c + " aborted after " + (System.currentTimeMillis() - t) + "ms");
                    }
                    return null;
                }
            }, 1000);
        }
        ex.shutdown();
        try {
            ex.awaitTermination(100000, TimeUnit.MILLISECONDS);
        } catch (final InterruptedException e) {
            e.printStackTrace();
        }
    }

    private void submitTask(final Callable<Object> c, final int timeout) {
        final TimedFutureTask tft = new TimedFutureTask(c, timeout);
        final Future<?> ft = ex.submit(tft.getCallable());
        tft.setFuture(ft);
    }

    static class TimedFutureTask {
        final static ScheduledExecutorService canceller = Executors.newSingleThreadScheduledExecutor();
        private Timer cancelTimer;
        private Callable<Object> timedCallable;
        private Future<?> f;
        private int timeoutMS;

        public TimedFutureTask(final Callable<Object> callable, final int timeoutMS) {
            this.timeoutMS = timeoutMS;
            timedCallable = (new Callable<Object>() {

                @Override
                public Object call() throws Exception {

                    cancelTimer = new Timer();
                    cancelTimer.schedule(new TimerTask() {

                        @Override
                        public void run() {
                            f.cancel(true);

                        }
                    }, timeoutMS);

                    final Object res = callable.call();
                    cancelTimer.cancel();
                    return res;
                }

            });
        }

        public Callable<Object> getCallable() {
            return timedCallable;
        }

        public void setFuture(final Future<?> future) {
            f = future;
        }
    }

}
于 2012-11-05T21:47:42.390 に答える
0

手動で実行できますが、単純なタスクを実行するにはコードが多すぎます:(

public void run() {
    long start = System.nanoTime();
    long timeout = 60 * 1000;
    do {
        // Do work here
    } while (TimeUnit.MICROSECONDS.convert(System.nanoTime() - start,
            TimeUnit.MICROSECONDS)
            - start > timeout);
}
于 2012-11-05T17:18:59.223 に答える
0

サブミットしたタスクの一部としてタイマーを開始できるため、タスクの実行時に開始されます。この場合、future.cancel を使用することはできませんが、スレッドを中断することはできます。サブミットしたタスクによっては、適切かつタイムリーに終了するのが簡単かどうかはわかりません。

于 2012-11-05T17:19:46.770 に答える
0

私は ScheduleExecutorService を使用します。

final Future future = es.submit(myTask);
ses.schedule(new Runnable() {
    public void run() {
        future.cancel(true);
    }
}, timeout, timeUnit);
于 2012-11-05T16:50:36.143 に答える