5

無期限にループする傾向があり、タイムアウト機能が組み込まれていないサードパーティ関数 (runThird() など) を使用しています。ただし、それを強制終了することはできます (killThird())。これを行う適切な方法はありますか (つまり、いくつかの同時実行構造)?

これが私の試みです:

java.lang.Thread thread = new Thread(new Runnable(){
    @Override
    public void run(){
        try {
            Thread.sleep(TIMEOUT);
        } catch (java.lang.InterruptedException e){
            return;
        }
        killThird();
    }
});                                
thread.start();

RunThirdResult rtr = runThird();

if (thread != null){
    thread.interrupt();
}

しかし、スリープを使用してスレッドを作成するオーバーヘッドと、runThird() が返された場合にスレッドを中断するという工夫が好きかどうかはわかりません。

4

3 に答える 3

2

これには ScheduledExecutorService を使用します。殺されるようにスケジュールします。

volatile RunThirdResult rtr;

ScheduledExecutorService service = Executors.newScheduledThreadPool(1);

service.schedule(new Runnable(){
   public void run(){
      if(rtr == null) killThird();
   }
}, TIMEOUT_IN_MILLIS, TimeUnit.MILLISECONDS);

RunThirdResult rtr = runThird();
于 2013-06-12T13:31:40.570 に答える
0

そんな感じ?最も興味深い部分はStoppableWrapper#stop()、グレースフル キャンセルは難しいことであり、すべてのケースに共通のアプローチはありません。あるときはファイルシステムをクリアする必要があり、別のときはネットワーク接続を閉じる必要があります。あなたのサンプルでは、​​ を呼び出すだけなので、名誉が中断されるとinterrupt()想定し、背後にあるものをきれいにするように注意します。runThird()

class Sample {
    final ExecutorService tasksExecutor = Executors.newCachedThreadPool();

    class StoppableWrapper implements Runnable {
        private final Runnable task;
        private final CountDownLatch executed;

        StoppableWrapper(Runnable task, CountDownLatch executed) {
            this.task = task;
            this.executed = executed;
        }

        void stop() {
            // e.g. Thread.currentThread().interrupt()
        }

        @Override
        public void run() {
            task.run();
            executed.countDown();
        }
    }

    public void scheduleTimingOutTaskExecution(final long timeout) {
        final CountDownLatch executed = new CountDownLatch(1);

        final StoppableWrapper command = new StoppableWrapper(new RunThirdInstance(), executed);
        tasksExecutor.execute(command);
        tasksExecutor.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    if (!executed.await(timeout, TimeUnit.MILLISECONDS)) {
                        command.stop();
                        // additionally, you can make stop() return boolean after time-out as well and handle failure 
                    }
                } catch (InterruptedException e) {
                    // handle stopper exception here
                }
            }
        });
    }
}
于 2013-06-12T11:50:47.077 に答える