I am using ScheduledExecutorService to run threads at a fixed interval of 1 min.
One instance of ScheduledExecutorService runs one thread and another instance runs another thread.
Example:
ses1.scheduleAtFixRate(..) // for thread 1
ses2.scheduleAtFixRate(..) // for thread 2
I was encountering some exceptions by which the further execution stops. I want to catch the exception for a systematic shutdown of my application.
Should I handle the exception using a third thread that monitors both futures and handles the Exception or is there any other better way? Will it affect the other threads.
Any and all help is appreciated!
I was encountering some exceptions by which the further execution
stops.
That is the expected behavior of ScheduledExecutorService.scheduleAtFixRate() according to the specification :
If any execution of the task encounters an exception, subsequent
executions are suppressed.
About your need :
I want to catch the exception for a systematic shutdown of my
application.
Should I handle the exception using a third thread that monitors both
futures and handles the Exception or is there any other better way?
Handling the future return with ScheduledFuture.get() looks the right.
According to ScheduledFuture.scheduleAtFixedRate() specification :
Otherwise, the task will only terminate via cancellation or
termination of the executor.
So you don't even need to create a new scheduled future.
Just run two parallel tasks (with ExecutorService or two threads is also possible) that wait on get() of each Future and that stops the application in case of exception thrown in the task :
Future<?> futureA = ses1.scheduleAtFixRate(..) // for thread 1
Future<?> futureB = ses2.scheduleAtFixRate(..) // for thread 2
submitAndStopTheApplicationIfFail(futureA);
submitAndStopTheApplicationIfFail(futureB);
public void submitAndStopTheApplicationIfFail(Future<?> future){
executor.submit(() -> {
try {
future.get();
} catch (InterruptedException e) {
// stop the application
} catch (ExecutionException e) {
// stop the application
}
});
}
Related
Does ScheduledExecutorService take care of handling terminated thread and generates a new one?
In the example below if any one of my thread terminates due to Error, what happens to thread pool size?
While debugging, I could notice one of the threads created by this service got silently terminated without printing any log statement. On checking Thread dump, I could still see 32 threads were still there and none of them were blocked.
public class CacheManager
{
private static class CacheRefresher extends Thread
{
Cache cache;
public CacheRefresher(Cache cache)
{
this(cache);
}
#Override
public final void run()
{
try {
LOG.info("cache is getting refreshed for " + cache.type);
cache.refreshCache();
} catch (Exception e) {
String subject = "Cache refresh failed in BMW";
LOG.log(Level.WARN, subject + ". Exception thrown:", e);
}
}
}
public void refreshCaches(List<cache> caches)
{
ThreadFactory ourThreadFactory =
new NamedThreadFactory("CacheHandler", true);
ScheduledExecutorService scheduleService =
Executors.newScheduledThreadPool(32, ourThreadFactory);
initialDelay = 60;
for (Cache cache : caches) {
service.scheduleWithFixedDelay(new CacheRefresher(cache), initialDelay, 20, TimeUnit.SECONDS);
initialDelay += 2;
cacheContainers.add(cache);
}
}
}
Uncaught exceptions in scheduled tasks will not cause scheduler's threads to terminate. However, it will prevent the failing task from being re-scheduled. See the respective documentation for ScheduledThreadPoolExecutor.html#scheduleWithFixedDelay:
The sequence of task executions continues indefinitely until one of the following exceptional completions occur:
[...]
An execution of the task throws an exception. In this case calling get on the returned future will throw ExecutionException, holding the exception as its cause.
While the JavaDocs for Executors.newFixedThreadPool explicitly mention this:
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.
there is no such strong guarantee about the Executors.newScheduledThreadPool.
It is possible that it behaves the same in this regard, but that is an implementation detail you should not need to care about. The Executor service will provide/create enough threads to perform the given tasks.
As found in Javadoc newScheduledThreadPool(int) there always will be the specified amount of threads. Even if a thread will shutdown, there will be started another one. But in the first place, threads within the ScheduledExecutorService should be reused, even when a exception occurs within the Runnable.run().
And sure the threads are not blocked but waiting for new action to do...
I have a java-program which runs on a schedule and fetches some data from external sources via RFC calls. The RFC calls are threaded and shall be canceled after 60 seconds. This is how I do it:
Future<String> future = executor.submit(new MyCallable());
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
}
This worked for a long time until I came accross a situation, where the external RFC call became stuck and future.cancel(true) was unable to interrupt the thread-execution. So my java-program never finished and continued running until I manually canceled the corresponding process within the external system.
My question now is, how can one guarantee the code to finish in any situation? I saw that stopping the thread is depreciated.
Would it be a good idea to do sth like this?
try {
future.get(60, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
if(!future.isDone()){
System.exit(1);
}
}
Thanks for any ideas on this.
Cheers, Jooo
I believe that there's no way in Java to just kill off a thread if during execution not implemented InterruptedException . If the thread is executing, it just sets a flag and it's up to the thread to notice it. if the thread is waiting or sleeping, it will throw an InterruptedException.
No need to check after every line, of course, but methods which can take a long time to execute are responsible for properly handling interrupts
kill the process in which the thread is running. (E.g., call System.exit(int).)
I have spring scheduler method. And ExecutorService
#Scheduled(fixedRate = 5000)
public void startSchedule() throws IOException{
threadPool.submit(() -> {
if(.......)return;
try {
generate(reportTasck);
} catch (NurException | IOException e) {
e.printStackTrace();
}
});
}
Each 5 sec start my method and if a necessary condition - start new thread with my logic. How can I stop/pause particular thread?
I have button on veb page, and if I press it I need to stop my thread.
There is already quite some discussion on SO regarding the stopping of threads. For a variety of reasons you should not stop or kill a thread as e.g. noted here:
How do you kill a thread in Java?
In order to allow the thread to properly cleanup its resources it should be the thread's responsibility to terminate itself by e.g. periodically checking some condition using e.g. a shared variable or via the thread's interrupt flag. See this answer for more details:
How to stop a thread created by implementing runnable interface?
Should we set the interrupted flag when catching an InterruptedException inside a task managed by an ExecutorService? Or should we just swallow the InterruptedException?
Example:
final ExecutorService service = ...;
final Object object = ...;
service.submit(() -> {
try {
while (!condition) {
object.wait();
}
} catch (final InterruptedException exception) {
Thread.currentThread().interrupt(); // yes or no?
}
});
In a task submitted to an ExecutorService, receiving an interrupt is a signal to cancel execution of the task. So, in your code example, the answer is "no", don't set the interrupt again.
Re-asserting the interrupt status, as far as I can see in the source code, will be ignored, but it does waste a bit of work in the executor as an InterruptedException is raised immediately if the worker thread tries to get another task, which is then determined to be spurious and cleared based on the state of the executor.
Shutting down the executor in a timely manner depends on tasks exiting in response to an interrupt; it does not depend on tasks restoring the interrupt status.
As this good article suggest, don't ever swallow InterruptedException.
I have a few executor services which schedule local tasks such as reading a file, connecting to db etc. These processes do huge amount of logging, which is extensive based on the fact there are many threads running concurrently, writing their own thing into the log.
Now, at some point in time an exception can be raised, which reaches the main method where all exceptions are caught. I am then shutting down all the services and cancelling each task, hoping to prevent all further messages to the log. Unfortunately, the messages are still showing up after I shut everything down... Any ideas?
UPDATE:
Here is some code
public class Scheduler{
private final ExecutorService service;
private final ConcurrentMap<Object, Future<V>> cache;
...
public void shutDown() {
service.shutdownNow();
for (Future task : cache.values())
task.cancel(true);
}
The task will carry on running until it reaches a point where it detects the Thread has been interrupted. This can happen when calling some System or Thread functions and you may get an exception thrown. In your case you probably need to check yourself by calling
Thread.currentThread().isInterrupted()
It is a good idea to do this if your code runs loops and you are expecting to be stopped in this way.
When you shutdownNow your executor or call cancel(true) (by the way shutdownNow already cancels the already submitted tasks so your loop is unnecessary) your tasks get interrupted.
Depending on how they react to the interruption, they might then:
stop what they are doing immediately
stop what they are doing after a while, because the interruption signal is not being checked regularly enough
continue doing what they are doing because the interruption signal has been ignored
For example, if your tasks run a while(true) loop, you can replace it with something like:
while(!Thread.currentThread().isInterrupted()) {
//your code here
}
cleanup();
//and exit
Another example:
for (int i = 0; i < aBigNumber; i++) {
if (Thread.currentThread().isInterrupted()) { break; }
//rest of the code for the loop
}
cleanup();
//and exit
Another example, if you call a method that throws InterruptedException:
try {
Thread.sleep(forever); //or some blocking IO or file reading...
} catch (InterruptedException e) {
cleanup();
Thread.currentThread.interrupt();
//and exit
}
Executors support 2 approaches of shutdown
shutdown() : Initiates an orderly shutdown in which previously submitted tasks are executed, but no new tasks will be accepted. Invocation has no additional effect if already shut down.
shutdownNow() : 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.
Ref : http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()
- Try using the shutdowNow() method, it will shutdown all the task started by this Executor throwing InterruptedException, but IO and Synchronized operation can't be interrupted.
Eg:
ExecutorService executor = Executors.newFixedThreadPool();
executor.execute();
...
...
executor.shutdownNow();
- cancel(true) method can be used with submit() method to shutdown a particular task.