我遇到了停止执行任务的代码。
private final ExecutorService executor = Executors.newSingleThreadExecutor();
public void stop() {
executor.shutdownNow();
try {
executor.awaitTermination(100, TimeUnit.DAYS);
} catch (InterruptedException ex) {
log.error(null, ex);
}
}
public Runnable getRunnable() {
return new Runnable() {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// What if inside fun(), someone try to clear the interrupt flag?
// Say, through Thread.interrupted(). We will stuck in this loop
// forever.
fun();
}
}
};
}
我意识到,Runnable 可能会处于永远循环中,因为
- 未知的
fun
可能Thread.sleep
,清除中断标志并忽略InterruptedException
- 未知
fun
可能Thread.interrupted
,清除中断标志。
我想知道,下面的方法是修复代码的正确方法吗?
private final ExecutorService executor = Executors.newSingleThreadExecutor();
private volatile boolean flag = true;
public void stop() {
flag = false;
executor.shutdownNow();
try {
executor.awaitTermination(100, TimeUnit.DAYS);
} catch (InterruptedException ex) {
log.error(null, ex);
}
}
public Runnable getRunnable() {
return new Runnable() {
public void run() {
while (flag && !Thread.currentThread().isInterrupted()) {
// What if inside fun(), someone try to clear the interrupt flag?
// Say, through Thread.interrupted(). We will stuck in this loop
// forever.
fun();
}
}
};
}
最佳答案
没有办法确保未知函数结束。如果 fun 如下所示,您将无法在不关闭应用程序的情况下终止它。
void fun(){
while(true){
try{
...
}catch(Throwable th){
}
}
}
向 Runnable 添加标志在这里不会有帮助,因为 fun()
永远不会退出。一些旨在终止线程的方法(例如 Thread.destroy())已被弃用,因为它会使程序处于未知状态。
只有两种方法可以确保函数终止:
- 确保它遵循指定的行为。对于您来说,这将是:不要永远循环,不要清除中断标志或您自己的标志。
- 或者,在 jvm 的单独实例中运行该函数,如果该函数没有返回而不终止主程序,您可以终止 jvm。
如果您可以控制 fun()
或知道它最终会返回,那么添加您自己的标志将是一个有效的解决方案,您应该确保它处理如您所料有中断。
关于java - 这是停止执行任务的正确方法吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4707096/