Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Daemon threads scheduled on an ExecutorService; explain why this is bad form

Tags:

I'm comfortable with the idea of orderly shutdown on threads scheduled with an ExectuorService; that is to say, calling shutdown or shutdownNow will cause threads created on the pool to exit gracefully. If they respond to interrupt you can be sure finally etc will be called and you'll get a clean, predictable exit (where you can cleanup any resources etc).

However, if you've set your thread to be a daemon (via the executor's ThreadFactory) as below.

ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
   @Override
   public Thread newThread(Runnable runnable) {
      Thread thread = Executors.defaultThreadFactory().newThread(runnable);
      thread.setDaemon(true);
      return thread;
   }
});

after the main thread terminates, the VM will abruptly terminate any daemon threads. In the example above, a (daemon) thread scheduled and then abruptly terminated will bypass any finally blocks and any interruptable methods won't throw InterruptedException.

So, I tend to think that marking the threads used in a ThreadPoolExecutor's pool as daemon is bad practice... my question is really about helping me vocalise why.

Why is it bad practice (or not if you disagree) to use daemon threads in a ExecutorService's thread pool? In particular I'm interested in describing the life-cycle of the VM shutdown with graceful shutdown (threads that have an interruption policy and play nicely) vs daemon threads.

Expanding that last point, finalize on ThreadPoolExecutor will call shutdown on itself, but when it's using daemon threads, they could have terminated already if finalize was called by the VM. What's the behavior of the thread pool then? Can it be tricked into remaining alive (and so not exiting the VM) if underlying threads terminated abruptly?

Part of the reason I'm asking is because i've seen it used to bypass the need to shutdown the actual ExectorService. Can you think of scenarios where bypassing its shutdown life-cycle can have ill affect? So far, the only reason I can come up with for using daemons is to take a short cut and I want to appreciate any unexpected side affects it could cause.

like image 849
Toby Avatar asked Aug 23 '11 09:08

Toby


People also ask

Can threads be submitted to ExecutorService?

Once the thread has delegated the task to the ExecutorService , the thread continues its own execution independent of the execution of that task. The ExecutorService then executes the task concurrently, independently of the thread that submitted the task.

What are the advantages of using ExecutorService instead of creating threads directly?

ExecutorService abstracts away many of the complexities associated with the lower-level abstractions like raw Thread . It provides mechanisms for safely starting, closing down, submitting, executing, and blocking on the successful or abrupt termination of tasks (expressed as Runnable or Callable ).

What is a daemon thread why is it required?

In Java, Daemon Threads are one of the types of the thread which does not prevent Java Virtual Machine (JVM) from exiting. The main purpose of a daemon thread is to execute background task especially in case of some routine periodic task or work. With JVM exits, daemon thread also dies. By setting a thread.

What is a daemon thread?

A Daemon thread is a background service thread which runs as a low priority thread and performs background operations like garbage collection. JVM exits if only daemon threads are remaining. The setDaemon() method of the Thread class is used to mark/set a particular thread as either a daemon thread or a user thread.


2 Answers

is it bad practice to use daemon threads in a ExecutorService's thread pool?

If the tasks sent to that particular ExecutorService are ok to be terminated abruptly, then why not, that's what daemon threads do. But generally, there are not many tasks that are ok to be terminated with no shutdown ceremonies at all, so you must know what you're doing if you opt to daemon threads.

finalize() is called when an object is about to be garbage collected. There are no guarantees on when, if ever, any particular object will be GCd, and ThreadPoolExecutor is no exception, so its finalize() may or may not be called. The behavior depends on the particular JRE implementation, and even with the same implementation, may vary from time to time.

like image 146
Joonas Pulakka Avatar answered Oct 04 '22 04:10

Joonas Pulakka


Daemon threads can be useful, and if they weren't terminated abruptly, they wouldn't be so useful IMO.

Presumably we could imagine another type of thread, which are interrupted when no normal threads are running anymore, instead of being abruptly terminated. That may be a little convenient, but if you had to do any clean up at all, it's likely that you wanted to do an orderly clean up. This would limit the convenience of this feature.

On the other hand, if you had tasks that would not need any clean up at shutdown, deamon threads are quite convenient. And you wouldn't want to waste time waiting them to arrive at some specific state or risk a hang up on shutdown etc., because the reason you are using a deamon thread is because you don't need any kind of clean up. It would be a waste of time to execute anything if the app. is shutting down. If you care, then you shouldn't have used deamon threads.

It's no different with deamon thread pools. If that thread pool is doing tasks that do not need any clean up at shutdown, then it would make sense because of the convenience.

From the JCiP book:

Daemon threads should be used sparinglyfew processing activities can be safely abandoned at any time with no cleanup. In particular, it is dangerous to use daemon threads for tasks that might perform any sort of I/O. Daemon threads are best saved for "housekeeping" tasks, such as a background thread that periodically removes expired entries from an in-memory cache

like image 20
Enno Shioji Avatar answered Oct 04 '22 02:10

Enno Shioji