Turning an Executorservice to Daemon in Java

Turning an ExecutorService to daemon in Java

Probably simplest and preferred solution is in Marco13's answer so don't get fooled by vote difference (this answer is few years older) or acceptance mark (it just means that this solution was appropriate for OP circumstances, not that it is best in general).


You can use ThreadFactory to set threads inside Executor to daemons. This will affect executor service in a way that it will also become daemon thread so it (and threads handled by it) will stop if there will be no other non-daemon thread. Here is simple example:

ExecutorService exec = Executors.newFixedThreadPool(4,
new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});

exec.execute(YourTaskNowWillBeDaemon);

But if you want to get executor which will let its task finish, and at the same time will automatically call its shutdown() method when application is complete, you may want to wrap your executor with Guava's MoreExecutors.getExitingExecutorService.

ExecutorService exec = MoreExecutors.getExitingExecutorService(
(ThreadPoolExecutor) Executors.newFixedThreadPool(4),
100_000, TimeUnit.DAYS//period after which executor will be automatically closed
//I assume that 100_000 days is enough to simulate infinity
);
//exec.execute(YourTask);
exec.execute(() -> {
for (int i = 0; i < 3; i++) {
System.out.println("daemon");
try {
TimeUnit.SECONDS.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
}
});

ExecutorService with daemon threads - explicit shutdown

Well, as per setDaemon,

The Java Virtual Machine exits when the only threads running are all
daemon threads.

So because you're using daemon threads your executor won't prevent your application from finishing. But that's not to say there's no reason to call shutdown. You may still want to prevent any additional tasks from being submitted at some point before your application ends.


Test it if you like: (I removed the Guava stuff, but the principal is the same)

public static void main(String... args)
{
final ExecutorService executorService = Executors.newSingleThreadExecutor(r -> {
final Thread thread = new Thread(r);
thread.setDaemon(false); //change me
return thread;
});
executorService.submit(() -> { while (true){ System.out.println("busy"); } });
}

Executor and Daemon in Java

If you're using a scheduled executor, you can provide a ThreadFactory. This is used to create new Threads, and you can modify these (e.g. make them daemon) as you require.

EDIT: To answer your update, your ThreadFactory just needs to implement newThread(Runnable r) since your WebRunnable is a Runnable. So no real extra work.

Executor service or daemon threads which is better for multi threads?

I will hazard a guess that your ExecutorService is not working because you are calling get() on the Future instances it returns inside your loop. This mistake will indeed cause your processing to be serialized as if you had only one thread, because another task isn't submitted until the first completes.

If you really need to use Callable, don't get() the result until you are ready to block for some indefinite time as the tasks complete—and they can't complete if they haven't been submitted yet. For downloading URLs, it would be better to use Runnable, where the main thread submits URLs and then forgets about the task; the task can independently complete processing of its URL.

If you produce new tasks quickly, there's a chance you could queue up so many that you run out of memory. In that case, you can use a bounded queue and set up an appropriate rejection handler using ThreadPoolExecutor directly.

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

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.

How to better use ExecutorService in multithreading environment?

Should I use daemon or non daemon threads for my above use case?

It depends. But in this case I would prefer daemon threads because it is convenient to use clients which allows the process to exit.

Does that look right the way I am doing it?

No, it doesn't. Interrupting of an IO task is pretty hard. Try to set timeout in RestTemplate too. Canceling of the future in this case seems meaningless.

What is the difference if I catch Exception or RuntimeException?

If you don't have checked exceptions in try blocks there is no difference :) Just because only RuntimeExceptions possible in that case.

And one more important note: implementing sync call as async + waiting is bad idea. It is meaningless and consumes one thread from the thread pool per a call. Just create instance of the Task and call it in current thread!

How to implement a ScheduledExecutorService on top of a ExecutorService instance?

ScheduledExecutorService is available as part of Java language. If you want to make a separate wrapper over ExecutorService that would provide ScheduledExecutorService functionality you will have to write it yourself, but that would be a waste of time. What you need to do is to have your central ExecutorService instance to be an instance of ScheduledExecutorService. Note that ScheduledExecutorService extends ExecutorService and thus could be used as ExecutorService or ScheduledExecutorService as needed.

ExecutorService with huge number of tasks

Where are 200M tasks going to reside? Not in memory, I hope, unless you plan to implement your solution in a distributed fashion. In meantime, you need to instantiate an ExecutorService that does not accumulate a massive queue. Use with the "caller runs policy" (see here) when you create the service. If you try to put another task in the queue when it's already full, you'll end up executing it yourself, which is probably what you want.

OTOH, now that I look at your question more conscientiously, why not analyze a single file concurrently? Then the queue is never larger than the number of analyzers. That's what I'd do, frankly, since I'd like a readable log that has a message for each file as I load it, in the correct order.

I apologize for not being more helpful:

analysts.stream().map(analyst -> executor.submit(() -> analyst.analyze(file))).map(Future::get);

Basically, create bunch of futures for a single file, then wait for all of them before you move on.



Related Topics



Leave a reply



Submit