I want an object that will spawn a daemon thread that will continue to run for the lifetime of the process. Let's say, just for the sake of the argument, that it's a thread in an embedded system, and it waits to receive and handle commands on some diagnostic port. But, it could be anything really. The main idea is that it's watching something over a long period of time; It's not performing a sequence of tasks.
Common Java wisdom says, Never instantiate Thread
, Use an ExecutorService
instead. (E.g., see this answer) But what's the benefit? Using a thread pool as a means to create a single long-running thread seems pointless. How would it be any better than if I wrote this?
class Foobar {
public Foobar() {
this.threadFactory = Executors.defaultThreadFactory();
...
}
public Foobar(ThreadFactory threadFactory) {
this.threadFactory = threadFactory;
...
}
public void start() {
fooThread = threadFactory.newThread(new Runnable() { ... });
fooThread.setDaemon(true);
fooThread.start();
}
...
}
Note: this question seems similar to mine, but the answers only say how to use a thread pool, not why.
Best Answer
I think that "Never" is too strong a word. It's more like the second rule of optimization: "Don't (yet)".
In my opinion, the primary reason to use an executor service is to manage the number of threads running. If you allow arbitrary classes to create their own threads, you may quickly find yourself with 1,000 CPU-bound (or constantly context-switching) threads. An executor service solves that problem, by providing constraints on thread creation.
A secondary reason is that properly starting a thread requires some thought:
System.exit()
to shut down your program.That said, there are certainly cases where it's appropriate to spin up threads rather than rely on a thread pool.
"Externally generated" is context dependent. The classic case is the thread at the end of a message queue or socket, which needs to poll that queue and perform some action (which may involve dispatching a task to a pool).
However, it could also refer to events generated outside a particular module: for example, I consider it perfectly reasonable that Log4J's
AsyncAppender
spins up its own thread rather than expecting the application to provide a pool.