简体   繁体   English

“由于故障导致的线程终止”是指什么?

[英]What does 'Thread termination due to failure' refer to?

The javadoc for ExecutorService sometimes refers to the case when a Thread terminates 'due to failure'. ExecutorService的javadoc有时指的是Thread因“失败”而终止的情况。 However, it is not clear what kind of failure does this refer to. 但是,目前尚不清楚这是指什么样的失败。

For instance, the single thread executor documentation says that 例如, 单线程执行程序文档说明了这一点

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 如果这个单线程由于在关闭之前执行期间的故障而终止,那么如果需要执行后续任务,则新线程将取代它

I would have thought that this situation might happen in case of an Exception, or maybe a RuntimeException , but it does not seem to be the case. 我原以为这种情况可能发生在Exception或者RuntimeException的情况下,但似乎并非如此。 Running the following code seems to be giving the same thread name and thread ID. 运行以下代码似乎给出了相同的线程名称和线程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());
});

The output of this code is: 此代码的输出是:

Hello from pool-1-thread-1 12
Hello 2 from pool-1-thread-1 12

It seems that the same thread is being reused even in the case of NullPointerException . 即使在NullPointerException的情况下,似乎也在重用相同的线程。

So what kind of 'failure' is the Javadoc referring to? 那么Javadoc指的是什么样的“失败”?

This is an interesting question. 这是个有趣的问题。 Following the code in ThreadPoolExecutor the thread is discarded when a Runnable is passed to the execute() method. ThreadPoolExecutor的代码之后,当Runnable传递给execute()方法时,线程被丢弃。

When you call submit() the executor creates a wrapper for the callable/runnable of type FutureTask . 当您调用submit() ,执行程序为FutureTask类型的可调用/可运行创建一个包装器。 FutureTask.run() has some logic to catch exceptions and store them (so then, you can query this from the Future ). FutureTask.run()有一些逻辑来捕获异常并存储它们(所以,你可以从Future查询它)。 In this case, the exception never reaches the ThreadPool , so the thread is not discarded. 在这种情况下,异常永远不会到达ThreadPool ,因此不会丢弃该线程。

Augusto is right. 奥古斯托是对的。 Runnable tasks should have discarded the Thread after encountering the exception when they have passed as parameter in execute() method. Runnable任务应该在遇到异常时丢弃线程,因为它们在execute()方法中作为参数传递。

I have found concrete evidence regarding swallowing of exceptions by Future tasks at this article and Future Task source code 我已经在本文Future Task源代码中找到了有关吞噬未来任务异常的具体证据

**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);
   }

There are few more interesting questions in SE around this topic. 关于这个主题,SE中有一些更有趣的问题。

Catching thread exceptions from Java ExecutorService 从Java ExecutorService捕获线程异常

Choose between ExecutorService's submit and ExecutorService's execute 在ExecutorService的提交和ExecutorService的执行之间进行选择

EDIT: 编辑:

Thread failure or termination will happen when an exception is uncaught in the thread code. 当线程代码中未捕获异常时,将发生线程故障或终止。 If you submit task by execute() instead of submit() , exception won't be caught unless you catch the exception. 如果通过execute()而不是submit()提交任务,则除非捕获异常,否则不会捕获异常。 Uncaught exception by the thread code will result thread to terminate or failure and new thread will be created by Executor . 线程代码未捕获的异常将导致线程终止或失败,并且Executor将创建新线程

If you submit the task through submit(), a FutureTask will be created and that task will swallow uncaught exception by the code. 如果通过submit(),提交任务submit(),将创建FutureTask ,该任务将吞下未捕获的异常代码。 Since the exception was caught in FutureTask , the thread won't be discarded. 由于异常是在FutureTask中捕获的,因此不会丢弃该线程。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM