Graceful shutdown with spring and long-running threads - java

We have the problem that there are multiple async threads that process a bunch of data and need minutes or some of them even hours to end. The pod also processes some other short running request.
It might occur that the pod has to be moved, and a shutdown will happen during this processing. In this case, we want the threads to finish their work in short term and leave a status, which we can use to process the remaining data.
We already use graceful.shutdown=enable.
The idea now is that we introduce a method with #PreDestroy in the bean that creates the async threads.
When this method is called, it will set a "shutdown" flag in a different bean. All the long-running threads check this flag during processing and will stop processing when it's true and write a clean state of their processing to the database.
This is more or less working ... but not all the time.
As I understood after getting the shutdown trigger at first, there is a configurable time spring.lifecycle.timeout-per-shutdown-phase where threads can continue processing their work without reduction in any of the needed resources. After the time is over, all the shutdownhooks are processed in an unknown order. This brings me to the thought that I might not have all the necessary resources for leaving a clean state, when I use the approach with the #preDestroy and the flag.
Is there a better solution to this?
Is there a need to add some more configuration to the threads like setAwaitTerminationSeconds(60); or setWaitForTasksToCompleteOnShutdown(true);?

What I found is, when using graceful.shutdown=enable and #PreDestroy in spring, that you need to synchronize the run() method and the #PreDestroy method (provided that both are in the same class):
#Service
public class MyClass implements Runnable {
private volatile boolean shutDown = false;
public MyClass( TaskScheduler taskScheduler) {
taskScheduler.scheduleWithFixedDelay(this, 100);
}
#PreDestroy
public synchronized void preDestroy() {
this.shutDown = true;
log.info("#PreDestroy Callback triggered for shutting down");
}
#Override
public synchronized void run() {
if (this.shutDown) {
this.shutdownCounter++;
return;
}
// put in here, whatever you long running task needs to do
}
And you need to make sure, that your run() method is not doing anything, when preDestroy() was already called, hence the shutdown- flag.
What the synchronize does is, that preDestroy() automatically waits until run() is finished regularly. Only then preDestroy() is called, and by setting the shutDown flag, it prevents that it starts another long running thread, even in case run() is called again. Instead run() returns immediately.
Because otherwise, when you don't synchronized, then the preDestroy() is called immediately after the spring - server get a shutdown signal but spring thinks if preDestroy() has run and finished successful, that it can shut down itself immediately. Which is not what you want, because then all run() threads gets interrupted.
I also found, that this example above does not work when using the #Scheduled- annotation (instead of calling taskScheduler.scheduleWithFixedDelay(this, 100) in the constructor)

Related

How to make sure a long running Java thread never die

I have a long running thread that does house keeping tasks. The failing of the thread is hard to detect given the system will not be immediately affected. I want to make sure this thread never dies. My understand is as long as the code catches everything (Throwable), it will never die. Here is the sample code:
while (true) {
try {
// house keeping logic
} catch (Throwable t) {
// do not do anything
}
}
Is my understanding correct? Is there a better way hosting long running background tasks? I know ScheduledExecutorService can schedule tasks periodically but if the task needs to keep checking some resource, it is probably more efficient to just put everything in a while loop.
You can't have guaranteed long-running thread. However, you can have re-spawning logic if something goes wrong with your thread.
What you can do is have a watcher that will check if the thread is running every x mins.
Please note, the watcher will fail if JVM is shut down or crashed. If you want to re-start the thread even if JVM shuts down, you need to have external monitoring. For this, you can use tools such as supervisord.
public class LongRunningThread extends Thread {
private volatile boolean IS_RUNNING = true;
#Override
public void run() {
while (IS_RUNNING) {
try {
// actions
this.houseKeep();
} catch (Exception e) {
}
}
}
private void houseKeep() {
// housekeeping logic here
}
}
class ThreadWatcher {
private Thread threadToBeWatched;
public ThreadWatcher(Thread threadToBeWatched) {
this.threadToBeWatched = threadToBeWatched;
}
#Scheduled(cron = "*/1 * * * *")
public void checkStatus() {
if (!threadToBeWatched.isAlive()) {
// Logic to restart the thread.
}
}
}
If the housekeeping logic includes some tasks that could be classified as periodic tasks ( e.g check the connectivity to some service once per 20 seconds ) - then you'd be better off with TimerTask
Some example could be of help.
If something (anything short of OOM) happens in the TimerTask - it won't affect the timer that is responsible for task scheduling.
A few points:
I would strongly recommend using ScheduledExecutorService or some other equivalent feature that may be provided by any tools or framework you are using (e.g. #Scheduled in Spring). There are lots of considerations in these situations that are not immediately obvious, and a well established and maintained library will deal with these.
Second, it is uncommon to poll for changes in this manner without some kind of delay. A typical scenario might require you to, for example, close connections with machines that haven't responded in 1 minute. For this sort of loop, you don't need to be constantly checking, as the above loop will do. At the very least, you should include a call to Thread.sleep() to prevent excessive resource use. (This is another issue that ScheduledExecutorService deals with nicely).
Finally, you should include some way to gracefully exit the loop when your application terminates. A simple boolean running = true; on the class would suffice, and you then change your loop to: while (running) {...}. When you want to exit, simply set running = false; and your loop will exit.

Thread with capability of stopping it in any duration of time

is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
I wrote something like this
public class ThreadRunner {
private ExecutorService threadPoolExecutor;
ThreadRunner() {
threadPoolExecutor = Executors.newSingleThreadExecutor();
}
public void startThread(String endPoint, ProgressBar progressBar) {
Runnable task = () -> {
// some code which saves images from URL (1230 images) and updates progress bar
};
threadPoolExecutor.execute(task);
}
public void stopThread() {
threadPoolExecutor.shutdownNow();
}
}
Thread runs correctly, images are being saved, progress bar being updated, but when I want to stop thread (or maybe even pause process of saving if possible) by calling ThreadRunner class's method - nothing happens.
Am I doing something wrong - or most likely - what am I doing wrong?
is there any kind of Runnable, Callable or Thread with capability of stopping it in any duration of time?
You can implement such a thing yourself, but there is no generic support available for it, unless you count the long-deprecated Thread.stop() methods. Under no circumstances should you use those methods, but do read their API docs for a discussion of why they are deprecated and what you can do instead. You can find a longer-form version of the discussion in Java's technical notes.
The bottom line is that the computation you want to be able to stop needs to periodically check some shared variable or built-in condition to determine whether to do so. You arrange for that variable to be set when you want the thread to stop, and if you need to block until it does stop then you join() it. Under some circumstances, it can be helpful to interrupt() the thread to get it to check the variable (or being interrupted can itself serve as the termination condition). The user-facing end of this can be wrapped up in a method.
In any case, an ExecutorService cannot give you a handle on this. Requesting such a service to shut down will prevent it from dispatching any more tasks, but there is no safe, general-purpose mechanism by which it could force a premature shutdown of tasks that are already running.
Once started, a thread will run until Runnable.run() exits. Due to several issues you should never use Thread.stop() or Thread.interrupt().
Instead, you will have to implement your own logic for exit/pause. A few suggestions:
For stopping the thread, you can make a boolean variable shouldExit. In your thread, check this variable every now and then, and just do "return" or break the for/while loop when it becomes true. Setting this variable from another thread should now make the downloader exit. If necessary, you should surround access to this variable with synchronized block as to prevent any race conditions.
For pausing the thread, you can use a similar approach. When you set a certain variable to true (e.g. isPaused), make the thread react by going into an Object.sleep(). This way, it won't consume any CPU during sleep. You can then use Object.notify() from another thread to "kick" the sleeping thread out ouf sleep. You will need a synchronized block here, too.

How to manage single thread execution properly?

I have a process that I want to be triggered by different sources.
Let's say we have one case where we habe some other process (let's call it "manualStarter") under certain conditions wants to trigger this main process. The main process takes a while to complete, let's say 10 seconds to 10 minutes. In case the process is already in progress while the manualStarter is trying to start it, it should not be queued more than once. The second process to trigger the start of the main process could be a "timedStarter" which would trigger the process once in a while, but only if the process is not running, else it would not queue the process to be triggered, instead would try it again some time later.
Now I've tried implementing this kind of process manager by using the isAlive() and join(), but it seems isAlive() is not reliable at all, until it changes its state to alive, 100 threads of this thread might get started (and do sometimes). So seems I couldn't rely on that.
Then I tried using the SingleThreadExecutor service which is closer to what I'm looking for, it's not blocking anything and it only allows a single thread to execute the process, so that's good, however I still don't know how to check the status/lock it properly, or how else I can ensure that the queue for starting the thread doesn't become larger than 1. I read a bit that semaphores are often used for similar kinds of tasks, but I am not sure how I could use them in this scenario.
So how could I achieve what I want? Do I need to implement my own ThreadPoolExecutor? How can I do it? Is there any better way?
Just use a shared flag so the manual starter knows if the thread is running. For example:
// Schedule this to run periodically via ScheduledExecutorService
class ManualStarter {
private final AtomicBoolen isRunning = new AtomicBoolean(false);
private ExecutorService exec = Executors.newSingleThreadedExecutor();
public void run() {
if (!isRunning.getAndSet(true)) {
// It wasn't running so this will start it
exec.submit(new MainProcess(isRunning));
}
}
}
class MainProcess extends Runnable {
private final AtomicBoolean isRunning;
MainProcess(AtomicBoolean isRunning) { this.isRunning = isRunning; }
#Override
public void run() {
// do whatever it does
isRunning.set(false);
}
}
Then somewhere you schedule the main thing to run periodically doing something like:
ScheduledExectorService sched = Executors.newScheduledThreadPool(1);
ManualStarter starter = new ManualStarter();
// Every 10 seconds will check if MainProcess is running and will start
// it if it's not
sched..scheduleAtFixedRate(starter, 0, 10, SECONDS);
You should rather use ExecutorService for that. There is couple of implementations available (including ScheduledExecutorService that allows you to schedule deffered and/or repeating tasks - check Executors). Just pick one that fits your needst the best.
As for conditional execution the task is simple. Define some sort of accessible flag that holds the current "state" of given task. If it is running - do nothing, if it is not running - schedule execution.
Simple example:
//our flag
private volatile AtomicBoolean isRunning=new AtomicBoolean(false);
public void scheduleTask(){
if(isRunning.get()){
return; // do nothing
}else{
synchronized(isRunning){
if(isRunning.get()){
return;
}else{
isRunning.set(true)
scheduleNewTask();
}
}
}
}
For any how-tos check the official Oracle's documentaion about Executors.
I have use AtomicBoolean in this example to mock "mutable" boolean. This can be done with boolean as well but synchronization needs to be done on different object (eg. dedicated private Object lock=new Object();)

How to use ExecutorService shutdown in Android application

Im writing an SDK that has a singleton class with ExecutorService. It looks something like this:
public class MySingleton {
private static MySingleton mInstance;
private ExecutorService mExecutorService;
private MySingleton() {
mExecutorService = Executors.newSingleThreadExecutor();
}
// ...
public void doSomething(Runnable runnable) {
mExecutorService.execute(runnable);
}
}
This SDK class is intended to be used throughout the application to run tasks/Runnables, and doSomething() function is to queue and run all Runnables in a single thread.
But one thing I couldn't figure out is when to call the ExecutorService.shutdown() method. If I call it like so:
public void doSomething(Runnable runnable) {
if (mExecutorService.isTerminated()) {
mExecutorService = Executors.newSingleThreadExecutor();
}
mExecutorService.execute(runnable);
mExecutorService.shutdown();
}
It would defeat the purpose of using one Thread because if the old Runnable is still running when doSomething() is called the 2nd time, there may be two different Threads running simultaneously. Of course I can have a function that manually shuts down the ExecutorService, but requiring the user of the SDK to explicitly call the shutdown function didn't seem appropriate.
Can anyone show me some tips on when/how to call ExecutorService.shutdown() in an Android application? Thanks
There is no good reason to call shutdown each time you execute some task. You might want to call shutdown when some part of your application is being closed/finished. Ie. when Service is being stopped - then if it used executors - then I suppose you should shutdown them - but actually the point is to allow all the tasks to finish before the service quit logic will perform some finishing code. ie. by using:
executors.shutdown();
if (!executors.awaitTermination(5, TimeUnit.SECONDS)) {
executors.shutdownNow();
}
as an example, such service could be used to download some files, user would ie. want to pause downloading - ie. by opening camera application (that might stop your application/service to reclaim its resources/memory).
In an Android application, there is no need to shutdown a singleton ExecutorService unless it has any idle thread. According to Android docs:
A pool that is no longer referenced in a program AND has no remaining
threads will be shutdown automatically. If you would like to ensure
that unreferenced pools are reclaimed even if users forget to call
shutdown(), then you must arrange that unused threads eventually die,
by setting appropriate keep-alive times, using a lower bound of zero
core threads and/or setting allowCoreThreadTimeOut(boolean).
So if you use Executors.newCachedThreadPool() or create a ThreadPoolExecutor with corePoolSize of 0, it will automatically be shutdown when the application process dies.

How does one stop a thread without a stop() method?

I have question about the Java threads. Here is my scenario:
I have a thread calling a method that could take while. The thread keeps itself on that method until I get the result. If I send another request to that method in the same way, now there are two threads running (provided the first did not return the result yet). But I want to give the priority to the last thread and don't want to get the results from the previously started threads. So how could I get rid of earlier threads when I do not have a stop method?
The standard design pattern is to use a local variable in the thread that can be set to stop it:
public class MyThread extends Thread {
private volatile boolean running = true;
public void stop() {
running = false;
}
public void run() {
while (running) {
// do your things
}
}
}
This way you can greacefully terminate the thread, i.e. without throwing an InterruptedException.
The best way really depends on what that method does. If it waits on something, chances are an interrupt will result in an InterruptedException which you handle and cleanly exit. If it's doing something busy, it won't:
class Scratchpad {
public static void main(String[] a) {
Thread t = new Thread(new Runnable() {
public void run() {doWork();}
});
t.start();
try {
Thread.sleep(50);
} catch (InterruptedException ie) {}
t.interrupt();
}
private static void doWork() {
for ( long i = 1; i != 0; i *=5 );
}
}
In the case above, the only viable solution really is a flag variable to break out of the loop early on a cancel, ala #inflagranti.
Another option for event-driven architectures is the poison-pill: if your method is waiting on a blocking queue for a new item, then you can have a global constant item called the "poison-pill" that when consumed (dequeued) you kill the thread:
try {
while(true) {
SomeType next = queue.take();
if ( next == POISON_PILL ) {
return;
}
consume(next);
}
} catch //...
EDIT:
It looks like what you really want is an executor service. When you submit a job to an executor service, you get back a Future which you can use to track results and cancel the job.
You can interrupt a Thread, its execution chain will throw an InterruptedException most of the time (see special cases in the documentation).
If you just want to slow down the other thread and not have it exit, you can take some other approach...
For one thing, just like exiting you can have a de-prioritize variable that, when set, puts your thread to sleep for 100ms on each iteration. This would effectively stop it while your other thread searched, then when you re-prioritize it it would go back to full speed.
However, this is a little sloppy. Since you only ever want one thing running but you want to have it remember to process others when the priority one is done, you may want to place your processing into a class with a .process() method that is called repeatedly. When you wish to suspend processing of that request you simply stop calling .process on that object for a while.
In this way you can implement a stack of such objects and your thread would just execute stack.peek().process(); every iteration, so pushing a new, more important task onto the stack would automatically stop any previous task from operating.
This leads to much more flexible scheduling--for instance you could have process() return false if there is nothing for it to do at which point your scheduler might go to the next item on the stack and try its' process() method, giving you some serious multi-tasking ability in a single thread without overtaxing your resources (network, I'm guessing)
There is a setPriority(int) method for Thread. You can set the first thread its priority like this:
Thread t = new Thread(yourRunnable);
t.start();
t.setPriority(Thread.MIN_PRIORITY); // The range goes from 1 to 10, I think
But this won't kill your thread. If you have only two threads using your runnable, then this is a good solution. But if you create threads in a loop and you always sets the priority of the last thread to minimum, you will get a lot of threads.
If this is what is application is going to do, take a look at a ThreadPool. This isn't an existing class in the Java API. You will have create one by yourself.
A ThreadPool is another Thread that manages all your other Threads the way you want. You can set a maximum number of running Threads. And in that ThreadPool, you can implement a system that manages the Thread priority automatically. Eg: You can make that older threads gain more priority, so you can properly end them.
So, if you know how to work with a ThreadPool, it can be very interesting.
According to java.lang.Thread API, you should use interrupt() method and check for isInterrupted() flag while you're doing some time-consuming cancelable operation. This approach allows to deal with different kind of "waiting situations":
1. wait(), join() and sleep() methods will throw InterruptedExcetion after you invoke interrupt() method
2. If thread blocked by java.nio.channels.Selector it will finish selector operation
3. If you're waiting for I/O thread will receive ClosedByInterruptException, but in this case your I/O facility must implement InterruptibleChannel interface.
If it's not possible to interrupt this action in a generic way, you could simply abandon previous thread and get results from a new one. You could do it by means of java.util.concurrent.Future and java.util.concurrent.ExecutorService.
Cosider following code snippet:
public class RequestService<Result> {
private ExecutorService executor = Executors.newFixedThreadPool(3);
private Future<Result> result;
public Future<Result> doRequest(){
if(result !=null){
result.cancel(true);
}
result = executor.submit(new Callable<Result>() {
public Result call() throws Exception {
// do your long-running service call here
}
});
return result;
}
}
Future object here represents a results of service call. If you invoke doRequest method one more time, it attempts to cancel previous task and then try to submit new request. As far as thread pool contain more than one thread, you won't have to wait until previous request is cancelled. New request is submitted immediately and method returns you a new result of request.

Categories