Wake up a thread spawned using ScheduledExecutorService - java

I am using ScheduledExecutorService to spawn a thread as below:
private ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
private ScheduledFuture<?> scheduledFuture = ses.scheduleWithFixedDelay(() -> { cleanup(); }, 0L, 5L, TimeUnit.SECONDS);
There is a sleep of 5 seconds in between executions of the cleanup function.
In certain conditions, is there a provision to wake this thread up to start running the cleanup instead of waiting for the 5 seconds to trigger it?
Example: at time T1 -> cleanup is called, at T1+2s -> i want to wake up the thread to do the cleanup explicity

i want to wake up the thread to do the cleanup explicity.
Why not simply call cleanup() from whatever other thread sees the need?
void someTerriblyImportantFunction(...) {
...
if (thisPlaceNeedsToBeCleanedUp_Like_NOW()) {
cleanup();
}
...
}
I can do that, but i wanted the thread to always run cleanup instead.
First of all, you can not depend on the thread pool to always use the same thread when it executes your cleanup task. You created the pool by calling Executors.newScheduledThreadPool(1), but theĀ 1 argument only specifies the minimum number of threads in the pool. In a program that uses the same thread pool for more than one thing, the pool is free to create and destroy worker threads as needed, so long as it always keeps one thread ready.
Secondly, and this is just my personal opinion, it's good practice to design your multi-threaded program in such a way that, whenever some task needs to be performed, it should not matter which thread performs it. In this case, I would design cleanup() so that it can be safely called at any time, from any thread.
P.S., Also note what #Hulk said in a comment: If cleanup() takes more time than the caller is willing to wait for, then another option would be to submit a "one-shot" task to be scheduled as soon as possible by the same thread pool.
void someTerriblyImportantFunction(...) {
...
if (thisPlaceNeedsToBeCleanedUp_RealSoon()) {
ses.schedule(() -> { cleanup(); }, 1L, TimeUnit.MICROSECONDS);
}
...
}

Related

Thread starvation deadlock example

In the book Effective Java by Joshua Bloch, there is this example (item 81):
// Simple framework for timing concurrent execution
public static long time(Executor executor, int concurrency,
Runnable action) throws InterruptedException {
CountDownLatch ready = new CountDownLatch(concurrency);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch done = new CountDownLatch(concurrency);
for (int i = 0; i < concurrency; i++) {
executor.execute(() -> {
ready.countDown(); // Tell timer we're ready
try {
start.await(); // Wait till peers are ready
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.countDown(); // Tell timer we're done
}
});
}
ready.await(); // Wait for all workers to be ready
long startNanos = System.nanoTime();
start.countDown(); // And they're off!
done.await(); // Wait for all workers to finish
return System.nanoTime() - startNanos;
}
It then says:
The executor passed to the time method must
allow for the creation of at least as many threads as the given concurrency level, or
the test will never complete. This is known as a thread starvation deadlock
[Goetz06, 8.1.1].
I am not sure why this would deadlock, e.g. with 1 one thread and two tasks. Do you have an example of a way it could deadlock?
TL;DR : The concurrency variable specifies the number of tasks to be executed by the threads in the Executor thread pool passed as parameter of the method time. A deadlock occurs if those tasks are not executed by different threads.
From the CountDownLatch documentation one can read:
A CountDownLatch is initialized with a given count. The await methods
block until the current count reaches zero due to invocations of the
countDown() method, after which all waiting threads are released and
any subsequent invocations of await return immediately.
Equipped with this information, let us imagining that each task is indeed be executed by a different thread. So each thread used from the Executor to run the parallel work:
() -> {
ready.countDown(); // Tell timer we're ready
try {
start.await(); // Wait till peers are ready
action.run();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
done.countDown(); // Tell timer we're done
}
}
will call first:
ready.countDown();
and then wait in start.await(); for the master thread to call start.countDown(); (which is the only thread doing it). However, before doing so, the master thread is waiting on:
ready.await();
for the remains threads to call ready.countDown(); concurrency times. So that the master thread can resume its work. Therefore, if each of those tasks are not executed by concurrency separate threads, those threads will wait for the master thread that in turn is waiting for them as well, hence a deadlock and the statement:
The executor passed to the time method must allow for the creation of
at least as many threads as the given concurrency level, or the test
will never complete.
So regarding your question:
I am not sure why this would deadlock, e.g. with 1 one thread and two
tasks. Do you have an example of a way it could deadlock?
So let us say that concurrency=2, and you have a thread on the Executor pool and the master thread. The master thread calls:
ready.await();
which was initialized as follows:
CountDownLatch ready = new CountDownLatch(concurrency);
therefore ready.countDown(); needs to be called at least twice. However, there is only one thread on the Executor pool that calls ready.countDown(); only once and then waits at:
start.await();
for the master thread to call start.countDown();, but that thread is still waiting on ready.await();. So both threads are waiting on each other, which leads to a deadlock.
A simple invocation that would deadlock:
time(Executors.newFixedThreadPool(1), 2, () -> System.out.println("Hello world"));
Here, an executor with just 1 thread is passed in. Since concurrency is 2, the one thread waits on the "Tell timer we're ready" line for another thread to decrease the counter again.
But there is no other thread to decrease the counter, because there's only one thread. So the only thread is blocked waiting.

Program does not terminate immediately when all ExecutorService tasks are done

I put a bunch of runnable objects into an ExecutorService:
// simplified content of main method
ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
threadPool.execute(new Worker());
}
I would expect my program/process to stop immediately after all workers are done. But according to my log, it takes another 20-30 seconds until that happens. The workers do not allocate any resources, in fact, they do nothing at the moment.
Don't get me wrong, this is not a crucial problem for me, I'm just trying to understand what is happening and I'm wondering if this is normal behavior.
Executors.newCachedThreadPool() uses Executors.defaultThreadFactory() for its ThreadFactory. defaultThreadFactory's javadocs say that "each new thread is created as a non-daemon thread" (emphasis added). So, the threads created for the newCachedThreadPool are non-daemon. That means that they'll prevent the JVM from exiting naturally (by "naturally" I mean that you can still call System.exit(1) or kill the program to cause the JVM to halt).
The reason the app finishes at all is that each thread created within the newCachedThreadPool times out and closes itself after some time of inactivity. When the last one of them closes itself, if your application doesn't have any non-daemon threads left, it'll quit.
You can (and should) close the ExecutorService down manually via shutdown or shutdownNow.
See also the JavaDoc for Thread, which talks about daemon-ness.
I would expect my program/process to stop immediately after all workers are done. But according to my log, it takes another 20-30 seconds until that happens. The workers do not allocate any resources, in fact, they do nothing at the moment.
The problem is that you are not shutting down your ExecutorService. After you submit all of the jobs to the service, you should shutdown the service or the JVM will not terminate unless all of the threads in it are daemon threads. If you do not shutdown the thread-pool then any threads associated with the ExecutorService, again if not daemon, will stop the JVM from finishing. If you've submitted any tasks to a cached thread pool then you will have to wait for the threads to timeout and get reaped before the JVM will finish.
ExecutorService threadPool = Executors.newCachedThreadPool();
for(int i = 0; i < workerCount; i++) {
threadPool.execute(new Worker());
}
// you _must_ do this after submitting all of your workers
threadPool.shutdown();
Starting the threads as daemon is most likely not what you want to do because your application may stop before the tasks have completed and all of the tasks will be terminated immediately at that time. I just did a quick audit and of the 178 times we use ExecutorService classes in our production code, only 2 of them were started as daemon threads. The rest are properly shutdown.
If you need to force an ExecutorService to stop when the application is exiting then using shutdownNow() with proper handling of the thread interrupt flags is in order.
Basically on an ExecutorService you call shutdown() and then awaitTermination():
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
...
}
From the javadoc for Executors.newCachedThreadPool():
Threads that have not been used for sixty seconds are terminated and removed from the cache.
It is usually a good idea to call shutdown() on an ExecutorService if you know that no new tasks will be submitted to it. Then all tasks in the queue will complete, but the service will then shut down immediately.
(Alternately, if you don't care if all the tasks complete - for example, if they are handling background calculations that are irrelevant once your main UI is gone - then you can create a ThreadFactory that sets all the threads in that pool to be daemon.)
For multi threading of ExecutorService
Solution is
threadPool.shutdown();
It is due to combination keepAliveTime=60L, timeunit=TimeUnit.SECONDS and corePoolSize=0*: when thread completes task, it does not terminate immediately, it may** wait during keepAliveTime for a new task.
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
*if core poolSize != 0 see method allowCoreThreadTimeOut() of ThreadPoolExecutor
**waiting depends on combination of current quantity of running threads in pool, corePoolSize and maximumPoolSize

How to implement a fixed rate poller with ScheduledExecutorService?

Given the following class:
public class Poller implements Runnable {
public static final int CORE_POOL_SIZE = 4;
public boolean running;
public ScheduledExecutorService ses;
public void startPolling() {
this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
this.ses.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);
}
public void run() {
running = true;
// ... Do something ...
running = false;
}
}
The ScheduledExecutorService has a core thread pool size of 4 but will more than one poller thread ever be created? Since this is passed into scheduleAtFixedRate does that mean there will only ever be one thread - or does something more complex happen behind the scenes?
And 2 bonus questions:-
Should running be static?
Is CORE_POOL_SIZE redundant?
The ScheduledExecutorService has a core thread pool size of 4 but will more than one poller thread ever be created?
It depends - if you run your program long enough, it will probably create 4 threads. If you quit after running your scheduled task only once or twice, you might only see 2 or 3 threads.
Why does it matter?
One way to monitor thread creation is to provide your own ThreadFactory:
this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE, new ThreadFactory() {
#Override
public Thread newThread(Runnable r) {
System.out.println("Creating thread");
return new Thread(r);
}
});
Should running be static?
It depends on what you want to achieve... Since you are not really it using in your example it is hard to say. You might need to make it static if you have several instances of Poller and you want them to not run concurrently for example.
Whether it is static or not, if you use it as a flag, you should make it volatile to ensure visibility.
Is CORE_POOL_SIZE redundant?
Not sure what you mean. It is a mandatory parameter so you need to provide a value. If you know for sure that no two execution will run concurrently, you could only have one thread. That will also prevent concurrent execution (so if one scheduled task needs to start but another is already running, the new one will be delayed).
scheduleAtFixedRate (Runnable, long initialDelay, long period, TimeUnit timeunit)
This method schedules a task to be executed periodically. The task is executed the first time after the initialDelay, and then recurringly every time the period expires.
If any execution of the given task throws an exception, the task is no longer executed. If no exceptions are thrown, the task will continue to be executed until the ScheduledExecutorService is shut down.
If a task takes longer to execute than the period between its scheduled executions, the next execution will start after the current execution finishes. The scheduled task will not be executed by more than one thread at a time.
Why do you put your executor service in Runnable class?
You should separate your ScheduledExecutorService as Singleton rather than being variable of runnable class.
Remind this ScheduledExecutorService is a thread container, so when you code this
this.ses = Executors.newScheduledThreadPool(CORE_POOL_SIZE);
it will create a lot of threads base on value of the size on the same time, when you put this code
this.ses.scheduleAtFixedRate(this, 0, 1, TimeUnit.SECONDS);
the ScheduledExecutorService will randomly pick a thread which idle to run this class every 1 second until it is finish. if you put sleep in run method that is longer than value of period time pass to scheduled thread, it wont create another thread until the 1st thread is finish. So if you want multiple thread run this Poller on the same time, then create multiple Poller instance and pass it to ScheduledExecutorService
CORE_POOL_SIZE its not redundant for me, its good to be a constant which value taken from configuration file.
Should running be static?
it's depends on what you need. if you intend to create multiple instance of Poller then u shouldn't

How to interrupt ExecutorService's threads

When using the ExecutorService returned by Executors.newSingleThreadExecutor(), how do I interrupt it?
In order to do this, you need to submit() a task to an ExecutorService, rather than calling execute(). When you do this, a Future is returned that can be used to manipulate the scheduled task. In particular, you can call cancel(true) on the associated Future to interrupt a task that is currently executing (or skip execution altogether if the task hasn't started running yet).
By the way, the object returned by Executors.newSingleThreadExecutor() is actually an ExecutorService.
Another way to interrupt the executor's internally managed thread(s) is to call the shutdownNow(..) method on your ExecutorService. Note, however, that as opposed to #erickson's solution, this will result in the whole ThreadPoolExecutor becoming unfit for further use.
I find this approach particularly useful in cases where the ExecutorService is no longer needed and keeping tabs on the Future instances is otherwise unnecessary (a prime example of this being the exit(..) method of your application).
Relevant information from the ExecutorService#shutdownNow(..) javadocs:
Attempts to stop all actively executing tasks, halts the processing of
waiting tasks, and returns a list of the tasks that were awaiting
execution.
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.
One proper way could be customizing/injecting the ThreadFactory for the ExecutorService and from within the thread factory, you got the handle of the thread created, then you can schedule some task to interrupt the thread being interested.
Demo code part for the overwrited method newThread in ThreadFactory:
ThreadFactory customThreadfactory new ThreadFactory() {
public Thread newThread(Runnable runnable) {
final Thread thread = new Thread(runnable);
if (namePrefix != null) {
thread.setName(namePrefix + "-" + count.getAndIncrement());
}
if (daemon != null) {
thread.setDaemon(daemon);
}
if (priority != null) {
thread.setPriority(priority);
}
scheduledExecutorService.schedule(new Callable<String>() {
public String call() throws Exception {
System.out.println("Executed!");
thread.interrupt();
return "Called!";
}
}, 5, TimeUnit.SECONDS);
return thread;
}
}
Then you can use below code to construct your ExecutorService instance:
ExecutorService executorService = Executors.newFixedThreadPool(3,
customThreadfactory);
Then after 5 seconds, an interrupt signal will be sent to the threads in ExecutorService.

ScheduledExecutorService multiple threads in parallel

I'm interested in using ScheduledExecutorService to spawn multiple threads for tasks if task before did not yet finish. For example I need to process a file every 0.5s. First task starts processing file, after 0.5s if first thread is not finished second thread is spawned and starts processing second file and so on. This can be done with something like this:
ScheduledExecutorService executor = Executors.newScheduledThreadPool(4)
while (!executor.isShutdown()) {
executor.execute(task);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// handle
}
}
Now my question: Why I can't do it with executor.scheduleAtFixedRate?
What I get is if the first task takes longer, the second task is started as soon as first finished, but no new thread is started even if executor has pool of threads. executor.scheduleWithFixedDelay is clear - it executes tasks with same time span between them and it doesn't matter how long it takes to complete the task. So probably I misunderstood ScheduledExecutorService purpose.
Maybe I should look at another kind of executor? Or just use code which I posted here? Any thoughts?
I've solved the problem by launching a nested anonymous runnable in each scheduled execution:
final ScheduledExecutorService service = Executors.newScheduledThreadPool(POOL_SIZE);
final Runnable command = new SlowRunnable();
service.scheduleAtFixedRate(
new Runnable() {
#Override
public void run() {
service.execute(command);
}
}, 0, 1, TimeUnit.SECONDS);
With this example there will be 1 thread executing at every interval a fast instruction, so it will be surely be finished when the next interval is expired. The remaining POOL_SIZE-1 threads will be executing the SlowRunnable's run() in parallel, which may take longer time than the duration of the single interval.
Please note that while I like this solution as it minimize the code and reuse the same ScheduledExecutorService, it must be sized correctly and may not be usable in every context: if the SlowRunnable is so slow that up to POOL_SIZE jobs get executed together, there will be no threads to run the the scheduled task in time.
Also, if you set the interval at 1 TimeUnit.NANOSECONDS it will probably became too slow also the execution of the main runnable.
One of the scheduleAtFixedRate methods is what you're looking for. It starts a task in a thread from the pool at the given interval, even if previous tasks haven't finished. If you're running out of threads to do the processing, adjust the pool size constraints as detailed in the ThreadPoolExecutor docs.

Categories

Resources