我正在使用第三方函数(比如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()返回时中断线程的设计。
答案 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
}
}
});
}
}