我想运行一个线程一段固定的时间。如果在该时间内没有完成,我想要终止它,抛出一些异常,或者以某种方式处理它。怎样才能做到呢?
我从这篇文章中找到了一种方法
是在线程的run()方法中使用一个TimerTask。
有没有更好的解决方案?
编辑:添加赏金,因为我需要一个更明确的答案。下面给出的ExecutorService代码没有解决我的问题。为什么我应该在执行(一些代码-我没有处理这段代码)后睡觉()?如果代码完成并且sleep()被中断,那怎么可能是timeOut呢?
The task that needs to be executed is not in my control. It can be any piece of code. The problem is this piece of code might run into an infinite loop. I don't want that to happen. So, I just want to run that task in a separate thread. The parent thread has to wait till that thread finishes and needs to know the status of the task (i.e whether it timed out or some exception occured or if its a success). If the task goes into an infinite loop, my parent thread keeps on waiting indefinitely, which is not an ideal situation.
确实应该使用ExecutorService而不是Timer,下面是一个SSCCE:
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
使用Future#get()方法中的timeout参数,例如,将其增加到5,您将看到线程结束。您可以在catch (TimeoutException e)块中拦截超时。
更新:为了澄清一个概念上的误解,sleep()不是必需的。它仅用于SSCCE/演示目的。只需要在sleep()的位置上执行长时间运行的任务。在长时间运行的任务中,你应该检查线程是否被中断,如下所示:
while (!Thread.interrupted()) {
// Do your long running task here.
}
确实应该使用ExecutorService而不是Timer,下面是一个SSCCE:
package com.stackoverflow.q2275443;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
public class Test {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new Task());
try {
System.out.println("Started..");
System.out.println(future.get(3, TimeUnit.SECONDS));
System.out.println("Finished!");
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Task implements Callable<String> {
@Override
public String call() throws Exception {
Thread.sleep(4000); // Just to demo a long running task of 4 seconds.
return "Ready!";
}
}
使用Future#get()方法中的timeout参数,例如,将其增加到5,您将看到线程结束。您可以在catch (TimeoutException e)块中拦截超时。
更新:为了澄清一个概念上的误解,sleep()不是必需的。它仅用于SSCCE/演示目的。只需要在sleep()的位置上执行长时间运行的任务。在长时间运行的任务中,你应该检查线程是否被中断,如下所示:
while (!Thread.interrupted()) {
// Do your long running task here.
}
下面的代码片段将在单独的线程中启动一个操作,然后等待最多10秒以使操作完成。如果操作没有及时完成,代码将尝试取消该操作,然后继续其愉快的方式。即使操作不能轻易取消,父线程也不会等待子线程终止。
ExecutorService executorService = getExecutorService();
Future<SomeClass> future = executorService.submit(new Callable<SomeClass>() {
public SomeClass call() {
// Perform long-running task, return result. The code should check
// interrupt status regularly, to facilitate cancellation.
}
});
try {
// Real life code should define the timeout as a constant or
// retrieve it from configuration
SomeClass result = future.get(10, TimeUnit.SECONDS);
// Do something with the result
} catch (TimeoutException e) {
future.cancel(true);
// Perform other error handling, e.g. logging, throwing an exception
}
getExecutorService()方法可以通过多种方式实现。如果您没有任何特殊的要求,您可以简单地调用Executors.newCachedThreadPool()进行线程池,没有线程数量的上限。