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).)
Related
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
}
});
}
I'm using an external lib (Generex) in my project, and one constructor may take a very long time to execute, so I'd like to have a timeout (let's say 50 ms), and be able to know if the timeout has been reached or not.
So I was thinking at using a dedicated thread, and wrote the following code:
#Test
public void isComputable() throws InterruptedException {
for (int i=0; i<10;i++)
System.out.println(check());
Thread.sleep(300000);
}
private static boolean check() {
final Thread stuffToDo = new Thread(() -> {while(true){}});
final ExecutorService executor = Executors.newSingleThreadExecutor();
final Future future = executor.submit(stuffToDo);
executor.shutdown();
try {
future.get(50, TimeUnit.MILLISECONDS);
}
catch (InterruptedException | ExecutionException | TimeoutException ie) {
stuffToDo.interrupt();
stuffToDo.stop();
return false;
}
if (!executor.isTerminated())
executor.shutdownNow();
return true;
}
I replaced the call to the external lib with a while(true) loop, yet it is important to note that, in my case, I cannot use a loop to check if the thread was interrupted.
When executing this code, I've got well the answer after 50 ms for each call, yet the thread is not destroyed, and there is a high CPU usage, as we can see with JProfiler (note that the loop in the test over i is just to have a nicer chart):
Does anyone have any idea on how to solve this issue please?
Note: I know that I should not use the deprecated stop method, I just tried everything I know to kill the thread.
You either have to check for an interrupt regularly in your code callex or you have to run the code in another process. These are the only ways you can either interrupt or kill the process running the code.
I suggest taking a stack trace of the long running thread to help fix it in the future.
I am trying to use a Third Party Internal Library which is processing a given request. Unfortunately it is synchronous in nature. Also I have no control on the code for the same. Basically it is a function call. This function seems to a bit erratic in behavior. Sometimes this function takes 10 ms to complete processing and sometimes it takes up to 300 secs to process the request.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs. I can live with not having the results and continue processing, but cannot tolerate a 3 min delay.
PS: This function internally sends an update to another system using JMS and waits for that system to respond and sends apart from some other calculations.
Can you suggest me a way to write a wrapper around this function so that it would throw an interrupted exception if the function does not complete processing with x ms/secs.
This is not possible. InterruptException only gets thrown by specific methods. You can certainly call thread.stop() but this is deprecated and not recommended for a number of reasons.
A better alternative would be for your code to wait for the response for a certain amount of time and just abandon the call if doesn't work. For example, you could submit a Callable to a thread pool that actually makes the call to the "Third Party Internal Library". Then your main code would do a future.get(...) with a specific timeout.
// allows 5 JMS calls concurrently, change as necessary or used newCachedThreadPool()
ExecutorService threadPool = Executors.newFixedThreadPool(5);
...
// submit the call to be made in the background by thread-pool
Future<Response> future = threadPool.submit(new Callable<Response>() {
public Response call() {
// this damn call can take 3 to 3000ms to complete dammit
return thirdPartyInternalLibrary.makeJmsRequest();
}
});
// wait for some max amount of time
Response response = null;
try {
response = future.get(TimeUnit.MILLISECONDS, 100);
} catch (TimeoutException te) {
// log that it timed out and continue or throw an exception
}
The problem with this method is that you might spawn a whole bunch of threads waiting for the library to respond to the remote JMS query that you would not have a lot of control over.
No easy solution.
This will throw a TimeoutException if the lambda doesn't finish in the time allotted:
CompletableFuture.supplyAsync(() -> yourCall()).get(1, TimeUnit.SECONDS)
Being that this is 3rd party you cannot modify the code. As such you will need to do two things
Launch the execution in a new thread.
Wait for execution in current thread, with timeout.
One possible way would be to use a Semaphore.
final Semaphore semaphore = new Semaphore(0);
Thread t = new Thread(new Runnable() {
#Override
public void run() {
// do work
semaphore.release();
}
});
t.start();
try {
semaphore.tryAcquire(1, TimeUnit.SECONDS); // Whatever your timeout is
} catch (InterruptedException e) {
// handle cleanup
}
The above method is gross, I would suggest instead updateing your desing to use a dedicated worker queue or RxJava with a timeout if possible.
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.
I have a Runnable implementation that does some work which might take some time and I am trying to schedule it using ScheduledThreadPoolExecutorwith scheduleAtFixedRate method. Now I want to ensure that shut down is graceful that means, Before terminating, task should be allowed to run completely. I have written following code for shutdown.
public void shutDown() throws Exception {
try {
LOG.info("Gracefully shutting down executor");
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
// cancels currently executing tasks.
LOG.info("Executor is still alive. Forcing executor thread pool to shut down");
executor.shutdownNow();
// Wait a while for tasks to respond to being cancelled
if (!executor.awaitTermination(SHUTDOWN_TIMEOUT, TimeUnit.SECONDS)) {
LOG.fatal("Executor thread pool did not terminate");
throw new Exception("Unable to shut down executor thread pool forcefully");
}
LOG.info("Executor shut down.");
}
} catch (Exception e) {
LOG.error("Exception shutting down executor", e);
throw e;
}
}
But problem with this is, I have to specify time to wait explicitly and I can not predict time taken by task in advance. Is there a way to make executor wait indefinitely until executing task finishes without having to mention time to wait? Or is there a better way to work on above scenario?
Thanks
Jitendra
Simplest solution is to "overprovision" so to speak. I suggest you use a huge timeout period that in no way can be exceeded by the time needed for a single task to execute, like:
// do you have tasks that can take more than 2^63 - 1 days to finish? :)
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
Use shutdown() to begin a graceful termination, and then use awaitTermination(long, TimeUnit) to wait for the executor service to finish shutting down.
As it was noted in the comment executor.shutdown() is not forcing any tasks to exit but rather it prevents new ones from being accepted. Have a look in the javadoc.
Another advice is if you want to get hold of your tasks as soon as they complete, you can implement Callable<T> instead of a Runnable that it's of a generic type and returns a value of type T. Then you can wrap this Callable<T> into a FutureTask<V> and submit that to your ScheduledThreadPoolExecutor. You can then loop through your tasks as soon as they have completed their work and are available. So in short something like this (notice as soon as we are done loading the scheduler with tasks it's safe to shut it down meaning that we don't allow any further tasks to be submitted from then on):
ScheduledExecutorService schedulerExecutor = Executors.newScheduledThreadPool(n);
Callable<Integer> myTask = . . .;
FutureTask<Integer> task = new FutureTask<Integer>(myTask);
schedulerExecutor.scheduleAtFixedRate(task, 0, 1, TimeUnit.SECONDS);
schedulerExecutor.shutdown();