5

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

3

让我们假设runThird()retuns Integer ...

// ...  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.
于 2013-06-12T12:17:26.543 回答
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 回答