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...
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 have code that schedules one-time tasks to execute and does this over and over. It looks something like this.
public static void main(String[] args)
{
while(true)
{
....
TimerTask closeTask = new CloseTask(cli);
Timer timer = new Timer(true);
timer.schedule(closeTask, (long) (iPeriod * 60 * 1000));
...
}
}
public class CloseTask extends TimerTask
{
Client client;
CloseTask(Client in_client)
{
client = in_client;
}
public void run()
{
try
{
for(int iRetries = 0; state == OPEN; iRetries++)
{
logger.log_trade_line_grablock( "Thread " + Thread.currentThread().getId() + ": About to send message", true, true, true, true, true);
client.send_mesg("close");
logger.log_trade_line_grablock( "Waiting 5 seconds before retrying ", true, true, true, true, true);
Thread.sleep(5000);
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
The intent of the run() method in the CloseTask class is to loop until the state variable changes from OPEN state to something else. However, intermittently the timer threads simply disappear, while state still equals OPEN, which I know by printing out all the thread ID's of the currently running threads every 5 minutes.
So my questions:
1) The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
2) If 1) is correct why isn't my try catch block catching these exceptions?
3) If 1) is correct is there a way to catch these exception that slip through uncaught?
Thanks for any insight into this issue.
You're creating a Timer instance, but not making sure that it doesn't get garbage collected.
From the documentation:
After the last live reference to a Timer object goes away and all outstanding tasks have completed execution, the timer's task execution thread terminates gracefully (and becomes subject to garbage collection).
So basically, you need to hold on to the reference to the Timer you created instead of just using a local variable.
The boolean you are passing in tells whether or not the thread created will be daemon. If it is daemon, the thread will be stopped once all non-daemon threads are finished. Since the only non-daemon thread being run in your application is the main thread then it will immediately be stopped after the main method is completed.
As Jon Skeet mentioned there is some completion operations done if no live thread is referencing the Timer and the tasks complete, but if it's daemon and the main method completes, it may not exit gracefully. To continue the documentation
... However, this can take arbitrarily long to occur. By default, the task execution thread does not run as a daemon thread, so it is capable of keeping an application from terminating. If a caller wants to terminate a timer's task execution thread rapidly, the caller should invoke the timer's cancel method.
To answer your question
The only explanation I can think of is that the CloseTask object is throwing uncaught exceptions. Is that correct?
If the JVM kills a non-daemon thread, it won't throw any exception. So you won't really know that it happened.
I have a function in Java. It normally returns a value after it completes its task. However, in some conditions it returns nothing. I create a runnable and run this function as a thread. However, because of its not returning a value, it does not finish although it does its task. The process stays alive because it waits a returning value. Is there a way to kill this thread after it is triggered or after a timeout? Stop() or Destroy() did not work. During debug, the thread is seen as alive and I want it to bi deleted/removed
Runnable runnable = new Runnable() {
#Override
public void run() {
int stat = RunMyFunction();
}
};
Thread thread = new Thread(runnable);
thread.start();
Java does not support killing a thread via any method on java.lang.Thread.
stop() and destroy() do look promising at first glance, but they have both been deprecated.
The documentation for destroy states:
This method was originally designed to destroy this thread without any cleanup. However, the method was never implemented. If if were to be implemented, it would be deadlock-prone
and stop:
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
Thus when the documentation says 'deprecated', what it really means is that they are broken and must never be used!?! The Java API designers put a lot of work into backwards compatibility of their APIs, where other languages would have removed these methods Sun decided to keep them as their internal guides (rightly or wrongly) do not permit the removal of a public api method.
So, the question remains. How is one to get a thread to exit from another thread? Sadly one must go out of ones way to poll an exit variable. This can be a custom variable, or it can be a standard flag within java.lang.Thread that is accessible via 'interrupted()'. The advantage of using interrupted() is that other Java APIs such as IO support this flag during otherwise blocking API calls and will exit throwing an InterruptedException. The detection of calling interrupt() is not immediate, as it sets a flag and relies on the Thread to poll the variable at some point in the future.
Oracle offers a tutorial on how to code using interrupt here.
The real problem you have is that RunMyFunction sometimes never terminates. As others have already stated, killing a thread is not intended in Java, so there is no good way to do it. Instead, you should reason about why you call a possibly non-terminating method. This looks like a code smell. Do the following:
If you are the author of RunMyFunction, make sure that it always terminates or it can be interrupted. You can do this by checking Thread.currentThread().isInterrupted() and throwing an InterruptedException when it is. E.g:
void run(){
while(...){ // this loop sometimes runs forever
if(Thread.currentThread().isInterrupted())
throw new InterruptedException(); // Now, we can "kill" this thread here
}
}
Using ExecuterService you can specify a timeout.
ExecutorService executor = Executors.newFixedThreadPool(1);
List<Callable<String>> tasks = new ArrayList<Callable<String>>();
tasks.add(new Callable<String>() {
#Override
public String call() throws Exception {
int stat = RunMyFunction();
return "Execution Finished";
}
});
new Thread(new Runnable() {
#Override
public void run() {
try {
executor.invokeAll(tasks, 10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).start();
invokeAll(...) is a blocking call so i've added inside a new thread.
Solution 1: Timed run: If you want a method to return or throw an exception after a specified amount of time, use the following method to execute the method on a background thread while waiting for it to complete:
public static void timedRun(Runnable r, long timeout, TimeUnit unit)
throws InterruptedException, TimeoutException {
Future<?> task = executor.submit(r);
try {
task.get(timeout, unit);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
} finally {
task.cancel(true);
}
}
private static RuntimeException launderThrowable(Throwable t) {
if (t instanceof RuntimeException) return (RuntimeException)t;
else if (t instanceof Error) throw (Error)t;
else throw new IllegalStateException("Not unchecked", t);
}
(Source: Goetz, Brian, Bloch, Joshua, Bowbeer, Joseph, Lea, Doug, Holmes, David and Peierls, Tim. Java Concurrency in Practice. : Addison-Wesley Longman, Amsterdam, 2006. Listing 5.13 and 7.10)
For executor, you can either create a new one using Executor.newSingleThreadExecutor(), or reuse an existing one.
But be warned: Although this method is guaranteed to return or throw an exception after the specified timeout, it cannot guarantee that the runnable will really stop! It interrupts the executing thread, but if the runnable does not react to thread interruption (e.g. by internally checking Thread.interrupted()), it may continue to run in the background - possibly forever - occupying a thread! But at least it does not block.
Solution 2: Timed run with custom threads: If there is any possibility beside thread interruption to cancel your method call, you can still use the approach above, but then you have to use an Executor with custom ThreadFactory that creates a special Thread instance with overridden interrupt method:
Executor executor = Executor.newSingleThreadExecutor(r -> new WsdlThread(r));
public class WsdlThread extends Thread {
public WsdlThread(Runnable r) { super(r); }
public void interrupt() {
try {
// TODO: do something that will interrupt the wsdl call
// e.g. close connection to server, etc.
// example: ((WsdlRunnable)r).getWsdlConnection().close();
} finally {
super.interrupt();
}
}
}
If this isn't possible too, and Thread.stop() doesn't work either, this last solution might work:
Solution 3: Start non-cancellable call in another JVM:
Use Runtime.exec to start another JVM and execute the method call there (See Executing a Java application in a separate process for more info on how to do this). Runtime.exec will return a Process object, which represents the running process.
You can kill it by calling destroy() or destroyForcibly().
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.
The following piece of code tries to accompolish this.
The code loops forever and checks if there are any pending requests to be processed. If there is any, it creates a new thread to process the request and submits it to the executor. Once all the threads are done,it sleeps for 60 seconds and again checks for pending requests.
public static void main(String a[]){
//variables init code omitted
ExecutorService service = Executors.newFixedThreadPool(15);
ExecutorCompletionService<Long> comp = new ExecutorCompletionService<Long>(service);
while(true){
List<AppRequest> pending = service.findPendingRequests();
int noPending = pending.size();
if (noPending > 0) {
for (AppRequest req : pending) {
Callable<Long> worker = new RequestThread(something, req);
comp.submit(worker);
}
}
for (int i = 0; i < noPending; i++) {
try {
Future<Long> f = comp.take();
long name;
try {
name = f.get();
LOGGER.debug(name + " got completed");
} catch (ExecutionException e) {
LOGGER.error(e.toString());
}
} catch (InterruptedException e) {
LOGGER.error(e.toString());
}
}
TimeUnit.SECONDS.sleep(60);
}
}
My question is most of the processing done by these threads deal with database. And this program will run on a windows machine. What happens to these threads when someone tries to shutdown or logoff the machine.? How to gracefully shutdown the running threads and also the executor.?
A typical orderly shutdown of an ExecutorService might look something like this:
final ExecutorService executor;
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
Logger.log("Executor did not terminate in the specified time."); //optional *
List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
}
}
});
*You can log that the executor still had tasks to process after waiting the time you were willing to wait.
**You can attempt to force the executor's worker Threads to abandon their current tasks and ensure they don't start any of the remaining ones.
Note that the solution above will work when a user issues an interrupt to your java process or when your ExecutorService only contains daemon threads. If, instead, the ExecutorService contains non-daemon threads that haven't completed, the JVM won't try to shutdown, and therefore the shutdown hooks won't be invoked.
If attempting to shutdown a process as part of a discrete application lifecycle (not a service) then shutdown code should not be placed inside a shutdown hook but at the appropriate location where the program is designed to terminate.
The book "Java Concurrency in Practice" states:
7.4. JVM Shutdown
The JVM can shut down in either an
orderly or abrupt manner. An orderly
shutdown is initiated when the last
"normal" (nondaemon) thread
terminates, someone calls System.exit,
or by other platform-specific means
(such as sending a SIGINT or hitting
Ctrl-C). [...]
7.4.1. Shutdown Hooks
In an orderly shutdown, the JVM first
starts all registered shutdown hooks.
Shutdown hooks are unstarted threads
that are registered with
Runtime.addShutdownHook. The JVM makes
no guarantees on the order in which
shutdown hooks are started. If any
application threads (daemon or
nondaemon) are still running at
shutdown time, they continue to run
concurrently with the shutdown
process. When all shutdown hooks have
completed, the JVM may choose to run
finalizers if runFinalizersOnExit is
true, and then halts. The JVM makes no
attempt to stop or interrupt any
application threads that are still
running at shutdown time; they are
abruptly terminated when the JVM
eventually halts. If the shutdown
hooks or finalizers don't complete,
then the orderly shutdown process
"hangs" and the JVM must be shut down
abruptly. [...]
The important bits are,
"The JVM makes no attempt to stop or interrupt any application threads that are still running at shutdown time; they are abruptly terminated when the JVM eventually halts." so I suppose the connection to the DB will abruptly terminate, if no shutdown hooks are there to do a graceful clean up (if you are using frameworks, they usually do provide such shutdown hooks). In my experience, session to the DB can remain until it is timed out by the DB, etc. when the app. is terminated without such hooks.
Since adding a shutdown hook to explicitly call shutdown() didn't work for me, I found an easy solution in Google's Guava:
com.google.common.util.concurrent.MoreExecutors.getExitingExecutorService.
You can either call shutdown() on the ExecutorService:
Initiates an orderly shutdown in which
previously submitted tasks are
executed, but no new tasks will be
accepted.
or you can call 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.
For example, typical implementations
will cancel via Thread.interrupt(), so
any task that fails to respond to
interrupts may never terminate.
Which one you call depends how badly you want it to stop....
I had similar issue, i use to get error like
o.a.c.loader.WebappClassLoaderBase :: The web application [ROOT] appears to have started a thread named [pool-2-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:
sun.misc.Unsafe.park(Native Method)
java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
Bellow code fixed it
private ThreadPoolExecutor executorPool;
#PostConstruct
public void init() {
log.debug("Initializing ThreadPoolExecutor");
executorPool = new ThreadPoolExecutor(1, 3, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
}
#PreDestroy
public void destroy() {
log.debug("Shuting down ThreadPoolExecutor");
executorPool.shutdown();
}