I'm using a thread pool to enable multiple unimportant tasks to be queued and (potentially) executed however I need to be able to easily cancel all queued and executing tasks and start a new queue from scratch.
ie:
// startup
pool = Executors.newFixedThreadPool(5);
// reset
pool.shutdownNow();
pool = Executors.newFixedThreadPool(5);
The implementation I'm using now seems to work but I'm not sure that shutting down completely and creating a new thread pool is particularly efficient.
The reset happens regularly, in some usages it happens just as regularly as scheduling a task! Since there is no way to determine if any tasks are awaiting execution (or is there?) I feel I am shutting down the pool way too often.
Is there a more suitable pool implementation or a better way to achieve this functionality?
EDIT: solution
I'm now running with:
// startup
pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(5);
// reset
for (Future<?> task : pool.getQueue().toArray(new Future[0]))
task.cancel(true);
I've ignored the call to 'purge' because this is slow and the queue will be tidied up later by the pool anyway. I am aware that currently executing tasks may not be terminated by this and that works for me.
thanks.
You could monitor all of the Futures you get from submitting the tasks and cancel() all of them which would allow you to re-use the thread-pool without recreated. However, I doubt that you would gain too much extra efficiency.
As long as you aren't doing this too often, I think your mechanism should work fine. One thing to realize is that although you are calling pool.shutdownNow(), this will only interrupt the running jobs which won't necessarily stop them. It depends on what they are doing and whether they are executing methods that throw InterruptedException often or listening to the thread interrupt flag. So even if shutdownNow() returns, some of the tasks may still be executing.
You can cancel all pending (and, probably running) tasks:
for (Future f: pool.getQueue().toArray(new Future[0]))
{
f.cancel(true); // or false
}
pool.purge();
Related
I have an ssh client library implementation. Each connection has few executors. One is the thread pool using ScheduledThreadPoolExecutor, that is used to queue short lived tasks and timers. One is the read executor, used to hold a packet receiver task. One is the write executor, serially executing tasks, of which each sends one packet to the server. Of course both read and write executor are single threaded, and write executor is used as something like a message queue.
The problem that i have is: methods to queue a message, and some methods queuing tasks, return a CompletableFuture. I queue stuff with CompletableFuture.runAsync method. However, the connection may be asynchronously closed in an orderly or forced manner. In that case some or all pools are shutdown using the shutdownNow method.
What to do in the case that some threads, including threads outside of those pools, could wait for some task to complete synchronously, and there is a risk of asynchronous shutdownNow due to everything including network errors? shutdownNow does not issue future's cancel method. I do not care if actual tasks are interrupted or not, i just care that futures will block indefinitely if executor was shutdown while their task was still in the queue.
What is the best practice to handle this situation? What do people do/etc?
Okay, i believe I have an idea. it is the following:
Because parallel shutdown waits for all tasks to complete, and shutdownNow will just trash them without cancelling, and because I actually end up using completable futures all the time, I decided to maintain a set of completable futures of all kinds per connection, that would hold all tasks including message senders and normal tasks submitted to the task pool. Each method that closes the connection or begins orderly disconnect or so will go through the set and complete all futures exceptionally with some exception. That gives better errors than cancellation. Also nothing should happen if the task will cancel itself this way.
Instead of using runAsync, or normally creating a completable future in case of tasks not associated to runnables, I have a special method that creates such a task, adds it to the set, and attaches a function using CompletableFuture.whenCompleted(), that removes the task from the set if it completed for any reason. I also have runAsync that creates the task using the previously described method, and then submits a runnable using CompletableFuture.completeAsync.
That way all waiting threads should unblock on connection close and get a nice exception from all tasks including sent messages, no matter which method I would use to wait for completion, get() or join().
I am fetching messages from Kafka and processing them using Executor service similar to below. I am not calling executorService.shutdown(). I have occasionally been seeing heapSize exception , but not sure if this could be one of the causes. How do the unused Runnable instances get removed after completion? Should I do anything specific to explicitly make it eligible for GC?
public class Consumer implements CommandLineRunner{
ExecutorService executorService;
executorService = Executors.newFixedThreadPool(50)
executorService.submit(runnable);
}
}
From documentation for Executors.newFixedThreadPool:
Creates a thread pool that reuses a fixed number of threads operating
off a shared unbounded queue. At any point, at most nThreads threads
will be active processing tasks. If additional tasks are submitted
when all threads are active, they will wait in the queue until a
thread is available. If any thread terminates due to a failure during
execution prior to shutdown, a new one will take its place if needed
to execute subsequent tasks. The threads in the pool will exist until
it is explicitly shutdown.
For given example there will be at most 50 threads active in the thread pool and they are released when you call shutdown method.
If you do not keep references to your Runnables they will be GCed when Executor is done with them. If you get out of memory exceptions this can be due to queued Runnables in cases when executor can not keep up with the work submitted to him.
EDIT: Also out of memory exceptions can happen if your tasks take a lot of memory (obviously).
My application requires that a certain job be done asynchronously, so I've resorted to the executor framework. This job (a Runnable) is expected to be run should a certain external interface be down (the vendor could be backed up for a while, say, 30 mins).
With this ask in mind, I believe I should maintain a single scheduled executor service with a fixed no. of core threads that perform these jobs when the interface I said above goes down for a brief moment (as a static variable in the class I need the thread pool in). I also don't think I should create an executor for every need to handle such a job (single scheduled thread pool executor), and shut down after a job is run, because that would defeat my purpose, wouldn't it? Because that could mean reserving a thread for every job during the backed up hour which sounds scary to me.
But, if I were to maintain such a single executor service, when would I be shutting down the executor? I understand that an executor once shut down can't be reused, while not shutting down the executor and keeping threads active could prevent the JVM from shutting down. How do I go about this?
My last statement was based on this from Effective Java 2nd edition:
And here is how to tell the executor to terminate gracefully (if you
fail to do this, it is likely that your VM will not exit):
executor.shutdown();
This job (a Runnable) is expected to be run should a certain external
interface be down (the vendor could be backed up for a while, say, 30
mins).
Above is your requirement. Now the solution entirely depends on how above situation is handled.
Trigger or event listener: If you have some trigger or event listener which can be called when it is found that a certain external interface is down, then in the that triggered code or event listener, you can create a ExecutorService, execute all your tasks (you can choose on fixed or pooled thread pool), and then on completion of all tasks, you can shutdown the ExecutorService
In this case, it is a good idea to create a ExecutorService, do tasks and shut it down. No need of long running ExecutorService.
Track or periodic check: If you have to track or check periodically whether certain external interface is down or not, then I think you can have a ScheduledThreadPoolExecutor implementation to have check after fixed time interval whether certain external interface is down or not, and if it is down then execute all your tasks. In this case you will NOT shutdown your ExecutorService and it will always be running.
Check scheduleAtFixedRate and scheduleWithFixedDelay for periodic task scheduling.
P.S.: Trigger and Track are my own convention I used tangentially as one word, so do infer it in technical words.
I understand that an executor once shut down can't be reused, while
not shutting down the executor and keeping threads active could
prevent the JVM from shutting down.
Yes, an executor once shut down can't be reused.
No, a running ExecutorService will not stop you JVM shutdown, but once JVM is shutdown that ExecutorService instance and its thread pool will be stopped and destroyed.
I am creating thread pools like this:
ExecutorService workers = Executors.newCachedThreadPool();
Invoking each pool tasks like this:
workers.invokeAll(tasks);
And after completion shutting those down like this:
workers.shutdown();
I have about 4 thread pools that do different procedures and those thread pools are being created from a servlet class.
What I want to do is shutdown all threads in those thread pools.
What is the cleanest way to achieve this?
Thanks
If all your worker tasks handle interrupts properly you could try to invoke:
workers.shutdownNow()
That call with typically send interrupts too all worker threads. However, proper interrupt handling is a bit implicit and the method documentation says that only a best effort attempt to stop the tasks is made. Hence, some JVM implementations might make a worse attempt than sending interrupts, why you might not want to trust this call.
You might want to look into other answers how to gracefully ensure proper shutdown of threads and implement such a solution for all your worker tasks, to guarantee proper shutdown. For example, in this answer, Jack explains the typical solution to have a volatile field that you can check in your workers. This field can be set from where you want to stop your tasks.
I've inherited some code that uses Executors.newFixedThreadPool(4); to run the 4 long-lived threads that do all the work of the application.
Is this recommended? I've read the Java Concurrency in Practice book and there does not seem to be much guidance around how to manage long-lived application threads.
What is the recommended way to start and manage several threads that each live for the entire live of the application?
You mentioned that code is using Executors, it should be returning an ExecutorService
ExecutorService executor = Executors.newFixedThreadPool(NTHREDS);
ExecutorService is an Executor that provides methods to manage termination and methods that can produce a Future for tracking progress of one or more asynchronous tasks.
As long as returned ExecutorService is performing graceful shutdown there should not be an issue.
You can check that your code is doing shutodwn by finding following in your code:
// This will make the executor accept no new threads
// and finish all existing threads in the queue
executor.shutdown();
// Wait until all threads are finish
executor.awaitTermination();
Cheers !!
I assume that your long-lived thread do some periodic job in a loop. What you can do is the following:
Make sure that each runnable in the pool checks the pool's state before looping.
while( ! pool.isShutdown() ) { ... }
Your runnable must thus have a reference to their parent pool.
Install a JVM shutdown hook with Runtime.addShutdownHook(). The hook calls pool.shutdown() then pool.awaitTermination(). The pool will transition to the SHUTDOWN state and eventually the threads will stop, after which it will transition to the TERMINATED state.
--
That said, I'm a bit suspicious of your 4 threads. Shouldn't there be only 1 long-live threads, which fetches tasks, and submits them to an executor service? Do you really have 4 different long-lived processes? (This consideration is orthogonal to the main question).