用于在错误进程周围包装超时的标准Java模式

时间:2013-06-12 10:38:36

标签: java concurrency

我正在使用第三方函数(比如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();
}

但我不确定我是否喜欢创建线程的开销,使用sleep以及在runThird()返回时中断线程的设计。

3 个答案:

答案 0 :(得分:3)

我们假设runThird()返回整数...

// ...  in your class ...
private ExecutorService executor = Executors.newCachedThreadPool();


//... then somewhere, where you want to call runThird()
Future<Integer> handle = executor.submit( new Callable<Integer>(){
    @Override Integer call(){
         return runThird(); // Assume you made it available here ...
    }
}

Integer result;
try{
   result = handle.get(TIMEOUT,UNIT); // TIMEOUT and UNIT declared somewhere above ...
}
catch(TimeoutException ex) {
   killThird();
   // HANDLE result not being set!
}

// ... use result.

答案 1 :(得分: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();

答案 2 :(得分: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
                }
            }
        });
    }
}