I'm new to java concurrency an would like to ask the following basic question. I'm creating a ThreadPoolExecutor for imporving performance as follows:
int n = Runtime.getRuntime().availableProcessors()
ExecutorService executor = Executors.newFixedThreadPool(n);
for( int i = 0; i < n; i++)
executor.execute(new Work());
After all thread in the thread pool have finished their tasks I need to shutdown the pool properly. I would tried this:
while(true){
if(executor.isTerminated()){
executor.shutdownNow();
break;
}
}
But I'm not sure about that because I think we waste a lot of processors resources to queriyng the executor for termination.
What is the right solution for that?
UPD: Runnable task:
public class Work implements Runnable{
private String sql;
public Work() {
//init sql
}
#Override
public void run() {
JdbcTemplate template = new JdbcTemplate(dataSource);
#SuppressWarnings("unchecked")
List<Integer> ints = template.queryForList(sql, Integer.class);
//Storing the list into a global cache
}
}
There seems to be something mystical around shutting down an ExecutorService.
From the documentation of shutdown():
Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted.
So all you have to do is to invoke shutdown() after you have submitted all your tasks, the exact time doesn’t matter. They don’t have to be completed at that time. The ThreadPoolExecutor will finish all tasks and then clean up all resources.
And it will do so regardless of whether you wait for it or not. So you don’t need to wait, just invoke shutdown() when you are confident that you will not submit new tasks, the rest will happen as soon as possible.
It says:
There are no guarantees beyond best-effort attempts to stop processing
actively executing tasks. For example, typical implementations will
cancel via Thread.interrupt(), so any task that fails to respond to
interrupts may never terminate.
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
So use awaitTermination instead. And for threads that take time, use a boolean variable as volatile and check it if it is set outside.If set then exit etc. something like that
try {
executor = Executors.newSingleThreadExecutor();
future = executor.submit(task);
executor.shutdown();
executor.awaitTermination(5, TimeUnit.SECONDS);
}
finally {
if (Objects.nonNull(executor) && !executor.isTerminated()) {
LOGGER.error("cancelling all non-finished tasks");
}
if (Objects.nonNull(executor)) {
executor.shutdownNow();
LOGGER.info("shutdown finished");
}
}
This way you shutdown executor and waiting for 5 seconds to complete all tasks and then finally calling executor.shutdownNow() to completely kill the executor.
This is the best way to shutdown executor.
Related
I want to return from my executeTasks() method only after all the tasks submitted to the threadpool are finished. Please note that my thread pool has configurable threadpoolsize and uses SynchronousQueue as the backing queue, so my for loop proceeds safely by submitting a task only if a thread is available. So, I just want to wait for the final tasks. I am using Phaser for this.
I've created a Phaser with 1 registered party i.e., the current thread and I register a new party to the Phaser before submitting a task to the threadpool, when the task finishes I deregister the task party. When for loop finishes by submitting the final tasks, I am hoping that my arriveAndAwaitAdvance() will wait for registered parties to arrive but it will only discover that all those parties are deregistered after some time and then move forward and return from my method.
I think that this will solve my problem. Please let me know if I am wrong or if there is any other better way to do this. Countdownlatch is not going to help as my threadpoolsize is configurable. I know that having a counter and monitor will solve this problem but I want out-of-the-box solution like Phaser.
private void executeTasks(TheadPoolExecutor threadPool, Iterator<String> it) {
final Phaser phaser = new Phaser(1);
for (final String id : IteratorUtils.iterable(it)) {
phaser.register();
threadPool.execute(() -> {
// phaser.arrive();
try {
thread.sleep(10000 * id.length());
} finally {
phaser.arriveAndDeregister();
}
});
}
phaser.arriveAndAwaitAdvance();
phaser.arriveAndDeregister();
}
I never used a Phaser before but I think a CountDownLatch is the better way to handle this task.
A CountDownLatch is a synchronization barier that allows one or more threads to wait until a set of operations being performed in other threads completes.
2 methods are useful when using a CountDownLatch :
countDown that decrements the counter when a task is finish.
await is for the current thread (main for instance) to wait the others to complete.
*
private void executeTasks(TheadPoolExecutor threadPool, Iterator<String> it) {
final CountDownLatch countDownLatch = new CountDownLatch(threadPool.getPoolSize());
for (final String id : IteratorUtils.iterable(it)) {
threadPool.execute(() -> {
try {
thread.sleep(10000 * id.length());
countDownLatch.countDown();
} catch (InterruptedException ex) {}
});
}
countDownLatch.await();
}
Here the CountDownLatch is initialized with the number of threads in the threadpool.
I have this simple schema:
int parallelism = 4; //4 tasks
ExecutorService executor = Executors.newCachedThreadPool();
CountDownLatch latch = new CountDownLatch(parallelism);
for(int i=0;i<parallelism;i++){
executor.execute(new MyTask());
}
latch.await();
System.out.println("done");
Where Task just calls
public void run(){
System.out.println("working");
latch.countDown();
}
Even though execution gives me:
working
working
working
working
done
the overall program keep executing! How come?
You need to shut down your Executor.
ExecutorService executor = Executors.newCachedThreadPool();
// ...
executor.shutdown();
while ( executor.awaitTermination(1, TimeUnit.SECONDS)) {
System.out.println("This is taking too long.");
}
Even though all of your runnables have completed the Executor keeps the threads in a pool. These are what is holding up your exit. The main thread will not exit until all non-daemon threads have completed.
Also see Turning an ExecutorService to daemon in Java for another alternative - making the Executor use daemon threads.
I am attempting to understand how to handle many instances of the ExecutorService executing Runnable commands. With regards to the code provided, how many shutdowns are required if I execute a hundred Runnables with the fixed thread pool set to one? I think the code should execute a hundred futures sequentially in the for loop execution order with a single thread (never spawns more than a single thread), and requires a single ExecutorService shutdown. Is this correct? Also, it's ok to call shutdown right after the for loop completes because all hundred of the futures are in queue so that the executorService shutdown will occur automatically after all hundred futures complete. Just looking for some clarification, thanks.
public static void main(String[] args)
{
private static ExecutorService executorService = Executors.newFixedThreadPool(1);
for (int i = 0; i < 100; i++)
{
executorService.execute(new Runnable() {
#Override
public void run()
{
// do stuff
}
});
}
executorService.shutdown();
}
Looks like you've got the right idea. It doesn't matter how many Runnables you've handed over to the ExecutorService to run or how big a thread pool you've allocated, you only need to call shutdown() once. That will allow all tasks to complete but will not allow you to add any new ones. You may want to call
try {
executorService.awaitTermination(5, TimeUnit.MINUTES);
} catch (InterruptedException e) {
// do stuff
}
to block while all tasks are completed depending on your usage scenario.
If you want to shutdown and attempt to kill all running tasks, instead call the shutdownNow() method. Note that there is no guarantee that it will be able to interrupt running tasks.
There's something odd about the implementation of the BoundedExecutor in the book Java Concurrency in Practice.
It's supposed to throttle task submission to the Executor by blocking the submitting thread when there are enough threads either queued or running in the Executor.
This is the implementation (after adding the missing rethrow in the catch clause):
public class BoundedExecutor {
private final Executor exec;
private final Semaphore semaphore;
public BoundedExecutor(Executor exec, int bound) {
this.exec = exec;
this.semaphore = new Semaphore(bound);
}
public void submitTask(final Runnable command) throws InterruptedException, RejectedExecutionException {
semaphore.acquire();
try {
exec.execute(new Runnable() {
#Override public void run() {
try {
command.run();
} finally {
semaphore.release();
}
}
});
} catch (RejectedExecutionException e) {
semaphore.release();
throw e;
}
}
When I instantiate the BoundedExecutor with an Executors.newCachedThreadPool() and a bound of 4, I would expect the number of threads instantiated by the cached thread pool to never exceed 4. In practice, however, it does. I've gotten this little test program to create as much as 11 threads:
public static void main(String[] args) throws Exception {
class CountingThreadFactory implements ThreadFactory {
int count;
#Override public Thread newThread(Runnable r) {
++count;
return new Thread(r);
}
}
List<Integer> counts = new ArrayList<Integer>();
for (int n = 0; n < 100; ++n) {
CountingThreadFactory countingThreadFactory = new CountingThreadFactory();
ExecutorService exec = Executors.newCachedThreadPool(countingThreadFactory);
try {
BoundedExecutor be = new BoundedExecutor(exec, 4);
for (int i = 0; i < 20000; ++i) {
be.submitTask(new Runnable() {
#Override public void run() {}
});
}
} finally {
exec.shutdown();
}
counts.add(countingThreadFactory.count);
}
System.out.println(Collections.max(counts));
}
I think there's a tiny little time frame between the release of the semaphore and the task ending, where another thread can aquire a permit and submit a task while the releasing thread hasn't finished yet. In other words, it has a race condition.
Can someone confirm this?
BoundedExecutor was indeed intended as an illustration of how to throttle task submission, not as a way to place a bound on thread pool size. There are more direct ways to achieve the latter, as at least one comment pointed out.
But the other answers don't mention the text in the book that says to use an unbounded queue and to
set the bound on the semaphore to be equal to the pool size plus the
number of queued tasks you want to allow, since the semaphore is
bounding the number of tasks both currently executing and awaiting
execution. [JCiP, end of section 8.3.3]
By mentioning unbounded queues and pool size, we were implying (apparently not very clearly) the use of a thread pool of bounded size.
What has always bothered me about BoundedExecutor, however, is that it doesn't implement the ExecutorService interface. A modern way to achieve similar functionality and still implement the standard interfaces would be to use Guava's listeningDecorator method and ForwardingListeningExecutorService class.
You are correct in your analysis of the race condition. There is no synchronization guarantees between the ExecutorService & the Semaphore.
However, I do not know if throttling the number of threads is what the BoundedExecutor is used for. I think it is more for throttling the number of tasks submitted to the service. Imagine if you have 5 million tasks that need to submit, and if you submit more then 10,000 of them you run out of memory.
Well you only will ever have 4 threads running at any given time, why would you want to try and queue up all 5 millions tasks? You can use a construct similar to this to throttle the number of tasks queued up at any given time. What you should get out of this is that at any given time there are only 4 tasks running.
Obviously the resolution to this is to use a Executors.newFixedThreadPool(4).
I see as much as 9 threads created at once. I suspect there is a race condition which causes there to be more thread than required.
This could be because there is before and after running the task work to be done. This means that even though there is only 4 thread inside your block of code, there is a number of thread stopping a previous task or getting ready to start a new task.
i.e. the thread does a release() while it is still running. Even though its the last thing you do its not the last thing it does before acquiring a new task.
I have a main for-loop that sends out requests to an external system. The external system might take a few seconds or even minutes to respond back.
Also, if the number of requests reaches the MAX_REQUESTS, the current for-loop should SLEEP for a few seconds.
This is my scenario. Lets say the main for-loop goes to sleep say for 5 seconds because it has reached the MAX_REQUESTS. Then say a previous external requests comes back returns from callExternalSystem(). What will happen to the main for-loop Thread that is currently on the SLEEP state? Will it be interrupted and continue processing or continue to SLEEP?
for(...){
...
while(numRequestsProcessing > MAX_REQUESTS){
Thread.sleep(SLEEP_TIME);
}
...
callExternalSystem();
}
Thanks in advance.
Unless you've got some code to interrupt the sleeping thread, it will continue sleeping until the required time has elapsed. If you don't want that to happen, you could possibly use wait()/notify() instead of sleep() so that another thread can notify the object that the main thread is sleeping on, in order to wake it up. That relies on there being another thread to notice that the external system has responded, of course - it's not really clear how you're getting responses back.
EDIT: It sounds like really you should use a Semaphore. Each time the main thread wants to issue a request, it acquires a permit. Each time there's a response, that releases a permit. Then you just need to set it up with as many permits as you want concurrent requests. Use tryAcquire if you want to be able to specify a timeout in the main thread - but think about what you want to do if you already have as many requests outstanding as you're really happy with.
I would use java.util.concurrent.Executors to create a thread pool with MAX_REQUESTS threads. Create a java.util.concurrent.CountDownLatch for however many requests you're sending out at once. Pass the latch to the Runnables that make the request, they call countDown() on the latch when complete. The main thread then calls await(timeout) on the latch. I would also suggest the book "Java Concurrency in Practice".
One approach, is to use a ThreadPoolExecutor which blocks whenever there is no free thread.
ThreadPoolExecutor executor = new ThreadPoolExecutor(MAX_REQUESTS, MAX_REQUESTS, 60, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new RejectedExecutionHandler() {
#Override
public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
try {
executor.getQueue().offer(r, Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
for(int i=0;i<LOTS_OF_REQUESTS;i++) {
final int finalI = i;
executor.submit(new Runnable() {
#Override
public void run() {
request(finalI);
}
});
}
Another approach is to have the tasks generate their own requests. This way a new request is generated each time a thread is free concurrently.
ExecutorService executor = Executors.newFixedThreadPool(MAX_REQUESTS);
final AtomicInteger counter = new AtomicInteger();
for (int i = 0; i < MAX_REQUESTS; i++) {
executor.submit(new Runnable() {
#Override
public void run() {
int i;
while ((i = counter.getAndIncrement()) < LOTS_OF_REQUESTS)
request(i);
}
});
}