java 最后执行线程失败_关于Java:“由于失败而终止线程”指的是什么?

ExecutorService的javadoc有时是指线程"由于失败"而终止的情况。 但是,尚不清楚这是指哪种故障。

例如,单线程执行程序文档说

if this single thread terminates due to a failure during execution

prior to shutdown, a new one will take its place if needed to execute

subsequent tasks

我本以为在Exception或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指的是哪种"故障"?

这不是知识,而是猜测,但是failure对我来说,它们的含义与软件无关。 也许这意味着硬件故障?

嗯...与硬件相关的故障听起来太过激烈了...在那种情况下为什么要启动另一个线程,好像什么也没发生? 我想与OS相关的线程终止可能是更合理的情况。

这是个有趣的问题。在ThreadPoolExecutor中的代码之后,将Runnable传递给execute()方法时,该线程将被丢弃。

当您调用submit()时,执行程序为FutureTask类型的可调用/可运行对象创建一个包装器。 FutureTask.run()具有一些捕获异常并将其存储的逻辑(因此,您可以从Future查询此异常)。在这种情况下,异常永远不会到达ThreadPool,因此不会丢弃线程。

那么,什么将导致线程失败,ExecutorService检测到它的失败并产生新的线程呢?

由于包装程序,在调用submit()时不会发生这种情况。 如果调用execute()且线程引发异常,则线程执行程序将生成一个新线程。 要对此进行测试,请使用您的代码并将submit()替换为execute(),您将看到执行程序创建了一个新线程。

奥古斯托是正确的。当Runnable任务作为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);

}

SE中围绕此主题还有一些其他有趣的问题。

从Java ExecutorService捕获线程异常

在ExecutorServices提交和ExecutorServices执行之间选择

编辑:

当线程代码中未捕获异常时,将发生线程故障或终止。如果您通过execute()而不是submit()提交任务,则除非您捕获到异常,否则不会捕获异常。线程代码未捕获到的异常将导致线程终止或失败,并且Executor将创建新线程。

如果通过submit(),提交任务,则会创建FutureTask,并且该任务将吞下代码中未捕获的异常。由于该异常是在FutureTask中捕获的,因此该线程不会被丢弃。

感谢您的回复。 我仍然不清楚它们指的是什么失败,这可能导致线程被丢弃并启动新线程。 您指示的代码清楚地表明已检查线程的状态。 我对导致线程死亡的原因更感兴趣(如果不是异常,无论如何都会被捕获)。

将来的异常会被吞下,但是使用execute()而不是Submit()提交的Runnable则不会。 如果遇到未捕获的异常,它们将死亡,并导致线程被丢弃。 更改代码以执行()并检查线程ID

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值