6

The javadoc for ExecutorService sometimes refers to the case when a Thread terminates 'due to failure'. 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. Running the following code seems to be giving the same thread name and thread 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.

So what kind of 'failure' is the Javadoc referring to?

jbx
  • 21,365
  • 18
  • 90
  • 144
  • This is more a guess than knowledge, but `failure` suggests to me that they mean something not software-related. Maybe they meant a hardware failure? – Turing85 Nov 15 '15 at 21:26
  • Mmm... hardware related failure sounds too drastic... why would it start another thread in that case, as if nothing happened? An OS related thread kill might be a more plausible case I guess. – jbx Nov 15 '15 at 23:01

2 Answers2

3

This is an interesting question. Following the code in ThreadPoolExecutor the thread is discarded when a Runnable is passed to the execute() method.

When you call submit() the executor creates a wrapper for the callable/runnable of type FutureTask. FutureTask.run() has some logic to catch exceptions and store them (so then, you can query this from the Future). In this case, the exception never reaches the ThreadPool, so the thread is not discarded.

Augusto
  • 28,839
  • 5
  • 58
  • 88
  • So what will cause a Thread to 'fail', the ExecutorService to detect its failure, and spawn a new Thread? – jbx Nov 15 '15 at 23:07
  • 2
    This won't happen when you call `submit()` because of the wrapper. If you call `execute()` and the thread throws an exception, the thread executor will spawn a new thread. To test this, take your code and replace the `submit()` with an `execute()` and you'll see that the executor creates a new thread. – Augusto Nov 16 '15 at 16:27
0

Augusto is right. Runnable tasks should have discarded the Thread after encountering the exception when they have passed as parameter in execute() method.

I have found concrete evidence regarding swallowing of exceptions by Future tasks at this article and Future Task source code

**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.

Catching thread exceptions from Java ExecutorService

Choose between ExecutorService's submit and ExecutorService's execute

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. Uncaught exception by the thread code will result thread to terminate or failure and new thread will be created by Executor.

If you submit the task through submit(), a FutureTask will be created and that task will swallow uncaught exception by the code. Since the exception was caught in FutureTask, the thread won't be discarded.

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
  • Thanks for your reply. Its still not clear to me what they are referring to as 'failure' which can cause a Thread to be discarded and a new Thread to start. The code you indicated clearly shows that a the state of the thread is checked. I am more interested in what would have caused a thread to die (if not an Exception, which is anyway caught). – jbx Nov 15 '15 at 23:05
  • Exception is swallowed for Future but not for Runnable submitted with execute () instead of submit (). They will die If uncaught exception is encountered and cause Thread to be discarded. Change your code to execute () and check thread Id – Ravindra babu Nov 16 '15 at 01:05