Java 什么是';故障导致的线程终止';提到
Java 什么是';故障导致的线程终止';提到,java,multithreading,executorservice,Java,Multithreading,Executorservice,ExecutorService的javadoc有时指线程“由于故障”而终止的情况。然而,不清楚这指的是什么样的失败 例如,文件上说 如果此单个线程在执行过程中由于故障而终止 在关闭之前,如果需要执行,将使用一个新的替换 后续任务 我本以为这种情况可能发生在异常的情况下,或者可能发生RuntimeException,但事实似乎并非如此。运行以下代码似乎给出了相同的线程名称和线程ID ExecutorService executor = Executors.newSingleThreadExecut
ExecutorService
的javadoc有时指线程“由于故障”而终止的情况。然而,不清楚这指的是什么样的失败
例如,文件上说
如果此单个线程在执行过程中由于故障而终止
在关闭之前,如果需要执行,将使用一个新的替换
后续任务
我本以为这种情况可能发生在异常的情况下,或者可能发生RuntimeException
,但事实似乎并非如此。运行以下代码似乎给出了相同的线程名称和线程ID
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> {
System.out.println("Hello from " + Thread.currentThread().getName()+ " " + Thread.currentThread().getId());
throw new NullPointerException("Test");
});
executor.submit(() -> {
System.out.println("Hello 2 from " + Thread.currentThread().getName() + " " + Thread.currentThread().getId());
});
此代码的输出为:
Hello from pool-1-thread-1 12
Hello 2 from pool-1-thread-1 12
即使在NullPointerException
的情况下,似乎也在重用同一个线程
那么Javadoc指的是哪种“失败”?这是一个有趣的问题。在
ThreadPoolExecutor
中的代码之后,当Runnable
传递给execute()
方法时,线程将被丢弃
调用
submit()
时,执行器会为类型为FutureTask
的可调用/可运行创建一个包装器FutureTask.run()
具有捕获异常并存储它们的一些逻辑(因此,您可以从未来的中查询该异常)。在这种情况下,异常永远不会到达线程池,因此线程不会被丢弃。Augusto是正确的Runnable
任务在execute()
方法中作为参数传递时,遇到异常后应该丢弃线程
我已经找到了具体的证据,证明在这个和这个阶段,未来的任务会接受异常
在SE中,围绕这一主题还有一些更有趣的问题
编辑:
当线程代码中没有异常时,将发生线程失败或终止。如果您通过execute()
而不是submit()
提交任务,则除非捕获异常,否则不会捕获异常。线程代码的未捕获异常将导致线程终止或失败,执行器将创建新线程
如果您通过submit()”提交任务,则将创建FutureTask
,该任务将吞噬代码未捕获的异常。由于异常是在FutureTask
中捕获的,因此线程不会被丢弃。这与其说是知识,不如说是猜测,但failure
对我来说意味着与软件无关的东西。可能是硬件故障?嗯。。。硬件相关故障听起来太严重了。。。在这种情况下,为什么它会启动另一个线程,好像什么都没发生?我想与操作系统相关的线程终止可能是一个更合理的情况。谢谢你的回复。我仍然不清楚他们所说的“失败”是什么,它会导致一个线程被丢弃,一个新线程启动。您所指示的代码清楚地显示线程状态已检查。我更感兴趣的是,是什么导致了线程死亡(如果不是异常的话,那么无论如何都会被捕获)。异常是为将来而存在的,但不是为Runnable提交的,它使用execute()而不是submit()。如果遇到未捕获异常并导致线程被丢弃,它们将死亡。将代码更改为execute()并检查线程IdSo什么将导致线程“失败”,executerservice将检测其失败并生成新线程?由于包装器的原因,在调用submit()
时不会发生这种情况。如果调用execute()
,线程抛出异常,线程执行器将生成一个新线程。要测试这一点,请获取代码并将submit()
替换为execute()
,您将看到执行器创建了一个新线程。
**Inside FutureTask$Sync**
void innerRun() {
if (!compareAndSetState(READY, RUNNING))
return;
runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
setException(ex);
return;
}
set(result);
} else {
releaseShared(0); // cancel
}
}
protected void setException(Throwable t) {
sync.innerSetException(t);
}