我有一个线程可能会卡住并永远保持运行。因此,经过一段时间后,我希望它停止执行,转到finally方法进行清理,然后死掉。我该如何安全地做到这一点?谢谢。
我对如何做到这一点的第一个想法是制作一个子线程并进行睡眠然后进行清理。但是当父线程仍在尝试运行时,它不能因此输出错误。
答案 0 :(得分:3)
将您的代码重构为Callable并使用ExecutorService获取Future。然后使用get超时,如果没有超时则抛出TimeoutException。有关完整示例,请参阅https://stackoverflow.com/a/2275596/53897。
答案 1 :(得分:0)
您需要为阻止呼叫设置超时。如果没有超时,抽象呼叫并以这种方式计时。</ p>
您可以创建1个线程,将任务轮询到其完成状态,如果超过某个值,则将其终止。任务本身仍然需要另一个线程。我通过创建具有staleness
值的任务来完成此操作。定期轮询所有任务,如果它们是陈旧的,则取消它们。
答案 2 :(得分:0)
建议1:如果你将代码放在带有wait()语句的try块中,你可以捕获的,然后将跟随finallyException。另一个线程必须发送notify()或notifyAll(),以便在需要中断线程的情况下导致中断。
建议2:我只是Java的初学者,但线程卡住意味着你必须能够在try / finally块中抛出自定义异常。
答案 3 :(得分:0)
<强>(1)强>
最佳解决方案是在超时时发送您的数据。应该看起来像
try {
mySendingDataLibraryApi.sendData(data, timeout /*, timeUnit */);
// some new APIs enable also to configure the time unit of the required timeout.
// Older APIs typically just use milliseconds.
} catch (TimeoutException e) {
doCleanup(); // your cleanup method.
}
<强>(2)强>
如果这不适用,因为您使用的API不公开此类配置,则第二个最佳解决方案是使用可中断的API sendData
方法并中断正在执行的线程。这依赖于提供这种可中断API的事实。如果API没有提供定时方法,我不会太依赖这种方法的存在......无论如何,执行任务的线程中的代码如下所示:
class MySendingDataRunnable implements Runnable {
@Override
public void run() {
try {
mySendingDataLibraryApi.sendDataInterruptibly(data);
} catch (InterruptedException e) {
doCleanup(); // your cleanup method.
// here either re-throw InterruptedExecption
// or restore the interrupted state with Thread.currentThread().interrupt();
}
}
}
线程调用者中的代码应该使用ExecutorService和Future方法返回的Future<?> submit(Runnable task)
实例,以便等待所需的时间并取消任务mayInterruptIfRunning
参数设置为true
:
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future<?> future = executor.submit(new MySendingDataRunnable());
try {
final Object noResult = future.get(60, TimeUnit.SECONDS); // no result for Runnable
} catch (InterruptedException e) {
// here again either re-throw or restore interupted state
} catch (ExecutionException e) {
// some applicative exception has occurred and should be handled
} catch (TimeoutException e) {
future.cancel(true); // *** here you actually cancel the task after time is out
}
<强>(3)强>
如果您使用的API不提供这些功能(定时/可中断的方法),您将必须使用您的创造力!您的这一行阻止代码必须阻止某些资源上的 。尝试联系此资源并将其关闭或断开连接,隐式导致任务终止。典型的例子是关闭网络连接。
注意:以上解决方案仅提供了一种实际取消任务并释放线程以执行其他任务的方法。 线程可能仍然存在。杀死线程通常不是您在任务完成时所做的事情(或者就此而言都是失败的)。当您为特定任务创建了一些不应该再次执行的线程时,这是可以接受的。在这种情况下,您使用上面的ExecutorService
并调用其shutdownNow()
方法。 甚至shutdownNow()
只会尽最大努力,通常取决于实际的任务是可以中断的......
Here's a detailed article(虽然有些陈旧但仍然如此)。