How to handle errors in a repeated task using ScheduledExecutorService? - java

I have a ScheduledExecutorService, which invokes a Runnable periodically via scheduleWithFixedDelay() (could have used scheduleAtFixedRate() instead).
Am now considering what to do if an error occurs. If it's something that can't easily be recovered from(*) I'd like the option of stopping all further invocations but not sure of the best way of doing this.
Apparently checked exceptions can't be thrown from a Runnable so would appreciate any guidance on how to choose from the following:
scheduledFuture.cancel(false);
...or...
scheduledFuture.cancel(true);
...or...
scheduledExecutorService.shutdown();
...or...
scheduledExecutorService.shutdownNow();
...or...
Throw a custom RuntimeException myself?
...or...
Something else?
(*) Would like to know the general case but in case anyone's interested, the checked exception I'm currently looking at is a ParserConfigurationException thrown from DocumentBuilderFactory.newDocumentBuilder(). If this is thrown, it indicates a serious problem so I'd basically like the scheduling to completely stop rather than potentially repeating the error every time.

You can use a Callable along with the Future perhaps. This will let you throw a checked exception from within an asynchronous task, yet still catch and handle as needed per task.
If you use that approach, then allowing the task itself to decide how to handle the exception probably makes the most sense. See this answer:
https://stackoverflow.com/a/4910682/123378 .
However, if you want to handle the exception outside of the task itself, then I think you will need another thread for each task. Here's one possible option:
ScheduledExecutorService scheduleExecutor;
scheduleExecutor = = Executors.newScheduledThreadPool(10); // or whatever
ExecutorService workerExecutor;
workerExecutor = Executors.newSingleThreadExecutor(); // or whatever
public void schedule(final long fixedDelay) {
scheduleExecutor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
Future<Void> future = workerExecutor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
// Do work here. Throw appropiate exception as needed.
return null;
}
});
// Now you can catch and handle the exception in whatever
// way you need to. You can cancel just this task (which is likely
// redundant by this point), or you can choose to shutdown
// all other scheduled tasks (which I doubt is what you want).
try {
future.get();
} catch (Exception e) {
future.cancel(true);
}
}
}, 0, fixedDelay, TimeUnit.MILLISECONDS);
}

Based on a few of the helpful comments above here's the gist of my current code - a few q's remain within so would welcome any further comments:
public class ScheduledTask implements Runnable {
// Configurable values
private static final int CORE_THREAD_POOL_SIZE = 1;
private static final int INITIAL_DELAY_MS = 0;
private static final int INTERVAL_MS = 1000;
private final ScheduledExecutorService scheduledExecutorService =
Executors.newScheduledThreadPool(ScheduledTask.CORE_THREAD_POOL_SIZE);
private ScheduledFuture<?> scheduledFuture;
public void run() {
try {
try {
// Do stuff
} catch RecoverableCheckedException rce { // E.g. SAXException
// Log and handle appropriately
}
} catch UnrecoverableCheckedException uce { // E.g. ParserConfigurationException
// Not 100% happy with this. It means the caller would need to call
// getCause() to get the real Exception in this case. But other
// RuntimeExceptions wouldn't be wrapped. Could consider catching
// and wrapping all RuntimeExceptions but I like that even less!
throw new RuntimeException(uce);
}
}
public boolean isScheduling() {
return (this.scheduledFuture != null)
&& (!this.scheduledFuture.isDone());
}
// May not be needed but provided in case this class is shared.
public boolean isShutdown() {
return scheduledExecutorService.isShutdown();
}
public void start() {
// If the Executor Service has already been shutdown, would expect
// a RejectedExecutionException to be thrown here(?) Not sure what
// would happen if this method were called when isScheduling() is
// true?
this.scheduledFuture =
this.scheduledExecutorService.scheduleWithFixedDelay(
this,
ScheduledTask.INITIAL_DELAY_MS,
ScheduledTask.INTERVAL_MS,
TimeUnit.MILLISECONDS);
}
// To be called once at the very end - e.g. on program termination.
public void shutdown() {
this.scheduledExecutorService.shutdown();
}
}

Related

What's the best way to release resources after java.util.Timer?

I have an AutoCloseable whose close() method is being called prematurely. The AutoCloseable is ProcessQueues below. I don't want the close() method to be called when it is currently being called. I'm considering the removal of "implements AutoCloseable" to accomplish that. But then how do I know when to call ProcessQueues.close()?
public class ProcessQueues implements AutoCloseable {
private ArrayList<MessageQueue> queueObjects = new ArrayList<MessageQueue>();
public ProcessQueues() {
queueObjects.add(new FFE_DPVALID_TO_SSP_EXCEPTION());
queueObjects.add(new FFE_DPVALID_TO_SSP_ESBEXCEPTION());
...
}
private void scheduleProcessRuns() {
try {
for (MessageQueue obj : queueObjects) {
monitorTimer.schedule(obj, new Date(), 1); // NOT THE ACTUAL ARGUMENTS
}
}
catch (Exception ex) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
#Override
public void close() throws Exception {
for (MessageQueue queue : queueObjects) {
queue.close();
}
}
}
I want ProcessQueues.close() to be called, but not until the task execution threads of all Timer objects terminate. As written, ProcessQueues.close() will be called as soon as the tasks are scheduled. I can easily solve that by removing "implements AutoCloseable" from the ProcessQueues class (and removing the #Override annotation). But then I have to call ProcessQueues.close() myself. How do I know when the task execution threads of all Timer objects have terminated? That's when I want to call ProcessQueues.close().
Note that MessageQueue isn't instantiated in the resource specification header of a try-with-resources block, so although MessageQueue also implements AutoCloseable, the feature isn't utilized here. I'm explicitly calling MessageQueue.close(). It is in MessageQueue.close() that I release resources. Releasing those resources prematurely causes the task execution threads to fail to complete their tasks.
I'm considering an explicit call to ProcessQueues.close() after rewriting the code to prevent automatic resource deallocation, but again I don't know how to discover the right time for that explicit call.
I considered overriding ProcessQueues.finalize(), but "Java: How to Program", Eleventh Edition advises against that. "You should never use method finalize, because it can cause many problems and there's uncertainty as to whether it will ever get called before a program terminates... Now it's considered better practice for any class that uses system resources... to provide a method that programmers can call to release resources when they're no longer needed in a program." I have such a method. It's ProcessQueues.close(). But when should I call it?
You have conflicting lifecycle issues here.
You have Timer whose lifecycle is 100% in your control. You start it, you stop it, and that's it. But you have no direct introspection in to the status of the threads being managed by the Timer. So, you can't ask it if it has anything currently running, for example.
Then you have your MessageQueue, which is invoked by the Timer. This is the lifecycle you're interested in. You want to wait for all of the MessageQueues to be "done", for assorted values of done. But, since the queue are constantly being rescheduled (given the Timer.schedule method that you're using), they're NEVER "done". They process their contents and go off and run again.
So, how is anyone to know when "done" means "done"?
Is it up to the MessageQueue? Or is it up to the ProcessQueues? Who's in command here?
Notice, nothing ever cancels the Timer. It's just runs on and on and on.
So, how can one know when MessageQueue can be closed?
If MessageQueue is the real driver here, then you should add lifecycle methods to the MessageQueue that ProcessQueues can monitor to know when to shut things down. For example, you could create a CountDownLatch set for however many MessageQueues are in your list, and then subscribe to a new lifecycle method on the MessageQueue that it calls when it's finished. The callback method can then decrement the CountDownLatch, and the ProcessQueues.close method simply waits on the latch to countdown before closing everything.
public class ProcessQueues implements AutoCloseable, MessageQueueListener {
private ArrayList<MessageQueue> queueObjects = new ArrayList<MessageQueue>();
CountDownLatch latch;
public ProcessQueues() {
queueObjects.add(new FFE_DPVALID_TO_SSP_EXCEPTION());
queueObjects.add(new FFE_DPVALID_TO_SSP_ESBEXCEPTION());
...
queueObjects.forEach((mq) -> {
mq.setListener(this);
});
latch = new CountDownLatch(queueObjects.size());
}
private void scheduleProcessRuns() {
try {
for (MessageQueue obj : queueObjects) {
monitorTimer.schedule(obj, new Date(), 1); // NOT THE ACTUAL ARGUMENTS
}
} catch (Exception ex) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
#Override
public void close() throws Exception {
latch.await();
for (MessageQueue queue : queueObjects) {
queue.close();
}
monitorTimer.cancel();
}
#Override
public void messageQueueDone() {
latch.countDown();
}
}
public interface MessageQueueListener {
public void messageQueueDone();
}
public class MessageQueue extends TimerTask {
MessageQueueListener listener;
public void setListener(MessageQueueListener listener) {
this.listener = listener;
}
private boolean isMessageQueueReallyDone {
...
}
public void run() {
...
if (isMessageQueueReallyDone() && listener != null) {
listener.messageQueueDone();
}
}
}
Mind, this means that your try-with-resource block will block waiting on all of the MessageQueues, if that's what you want, then you're good to go.
It also crassly assumes that your MessageQueue.run() knows when to shut down, which goes back to that "who's in control here" thing.
I could terminate the Timer, but having it run perpetually is intentional. The question is in consideration of what happens when something else terminates the Timer and the MessageQueue objects are no longer needed. It is at that point that I would like to call ProcessQueues.close().
If I were to use the Executor framework, rather than Timer, then I could use ExecutorService.awaitTermination(long timeout, TimeUnit unit)
TimerTask is a Runnable, and MessageQueue is already a TimerTask, so MessageQueue need not change.
'ExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS)' would effectively wait forever for termination.
public static void main(String[] args) {
try (ProcessQueues pq = new ProcessQueues()) {
pq.scheduleProcessRuns();
// Don't take this literally.
ExecutorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
} catch (Exception e) {
// NOT THE ACTUAL EXCEPTION HANDLER
}
}
Of course, awaitTermination isn't a static method, so I'll have to have an ExecutorService, but you get the idea.
After termination, the AutoCloseable feature is leveraged and ProcessQueues.close() is implicitly called.
All that remains is to start the threads for perpetually repeated calls to each TimerTask, using the Executor framework. The answer to that question is ScheduledExecutorService.
I think this will work.

How to deal with the situation when the ExecutorService ThreadFactory returns a null instead of a thead

I asked this question before but was unable to get it opened again as my update didn't kick of the reopen process. So resubmitting it
My question is how to get an ExecutorService to realize that the thread is not valid(null) straight away without having to wait for the get on the future.
I have a use case where when creating a thread in a ThreadFactory I want to return null if the Thread cannot be set up correctly(for example it cant connect to a server).
When the ExecutorService runs a submit on a callable and the ThreadFactory returns null as below the code will run but will wait at future.get(5, TimeUnit.SECONDS); and then throw a TimeoutException. The problem is that ThreadFactory.newThread() doesn't allow me to throw an exception here.
public class TestThreadFactory implements ThreadFactory {
#Override
public Thread newThread(Runnable r) {
// try to create a conneciton that fails
// I cannot throw an exception here, so if there is a problem I have to return null
return null;
}
}
public class ExecutorServicePool {
public static ExecutorService getService() {
return Executors.newFixedThreadPool(10, new TestThreadFactory());
}
}
public static void main(String[] args) {
ExecutorService executorService = ExecutorServicePool.getService();
Callable callable = new Callable<String>() {
#Override
public String call() throws Exception {
return "callable";
}
};
Future<String> future = executorService.submit(callable);
try {
future.get(5, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
executorService.shutdown();
}
You could throw a RuntimeException which feels like a sensible thing to do.
RuntimeExceptions are great for situations that are generally not recoverable. Not being able to connect to a database for example is a prime example of one of those situations. Basically in this scenario you want to say:
"Something is really wrong and at the minute I can't process your
request. Try again later"
RuntimeExceptions can be thrown in method implementations even if the Interface does not declare them. So you can update your ThreadFactory implementation to throw a RuntimeException rather than returning null. You could even create a specific RuntimeException sub-class to ensure that it is clear what the error is within your application e.g. FailedToInitialiseThreadException
You can create custom executor service by extending ThreadPoolExecutor and
override methods where threadfactory is called to get new thread, to your need.

How to stop a long running function

Consider this code:
class Solver {
private boolean abort = false;
public void solve(List<Case> cases) {
while(!abort) {
for(Case c : cases)
compute(c); // method that take too long to finish
}
}
// a bunch of methods
public void abort() {
abort = true;
}
}
// in another class
Solver solver = new Solver();
solver.solve(cases);
public void onSolveAborted() {
solver.abort();
}
How can I change this solution so I can abort the solve function instantly. I know I can implements the Runnable interface in Solver class so I can stop the thread. This will introduce many changes in our code and I don't know if the framework we are using allow creating threads.
This will not be possible without the use of threads. Something has to set abort() before the running thread will stop. Take a look at this example:
class Solver implements Runnable {
private List<Case> cases;
public Solver(List<Case> cases) {
this.cases = cases;
}
private void compute(Case c) {
try {
// Do some computation here
} finally {
// Sound the horns! Abandon ship!
}
}
public void solve(List<Object> cases) {
for (Case c : cases) {
try {
compute(c); // method that take too long to finish
} catch (InterruptedException e) {
// Hmm, maybe I should take the hint...
break;
}
}
}
public void run() {
solve(cases);
}
public static void main(String args[]) {
List<Case> cases = new ArrayList<Case>();
// Populate cases
Thread t = new Thread(new Solver(cases));
t.run();
do {
// Wait 30 seconds
t.join(30 * 1000);
// Not done yet? Lets drop a hint..
if(t.isAlive()) {
t.interrupt();
}
} while (t.isAlive());
}
}
Very simply, it launches solve in a thread. The main thread waits up to 30 seconds then interrupts solve method. The solve method catches the interruption and gracefully exits the computation. Unlike your solution using boolean abort, this launches an InterruptedException from anywhere in your thead code (and you should deal with the exception accordingly!) allowing you to halt execution at any time.
If you want more control, you can add the try.. catch inside compute so you can have a finally clause to close any opened files or whatnot. Perhaps better still, have a try.. finally in compute to deal with closing things in a "nice" way and the try.. catch (InterruptedException) in the solve method to handle what happens in the case of interruption (in short, cleanup logic and interruption logic don't have to be in the same method).
Do somthing like this
Let say, you have 100 cases, 10 has been solved and you want to abort remaing 90.
In your code, you are solving all the cases in one iteration, after that while loop check for abort.
public void solve(List<Case> cases) {
Iterator<Case> iterator = cases.iterator();
while (iterator.hasNext() && !abort) {
Case c=iterator.iterator.next();
compute(c);
}
}
Change your class to Runnable and use ExecutorService to run it. Then you can just use methods "shutDown()" or "shutDownNow()" methods. This is cleaner and less intrusive then what you suggested in your own question. Plus killing thread manually is a REALLY BAD idea. At some point in JDK itself in thread method "kill()" was killed as there is no clean way to do so properly

Java - Tasks and Futures - Do I need to catch exceptions or can I leave them to the Application Thread?

I'm writing a converter program using JavaFX, and am using the recommended javafx.concurrent.Task to do the heavy work away from the JavaFX Application Thread. I'm also using java.util.concurrent.Future and java.util.concurrent.ExecutorService within it to do extra work that can be done concurrently.
However a lot of the work involves methods that can potentially throw, and I need the process to stop in its tracks if that occurs. I'm currently spamming try-catch blocks everywhere and returning false rather than letting the exceptions bubble up.
But as call() in both Future and Task have the throws Exception declaration in case there are any uncaught ones, is it ok for me to just not catch the exceptions in the Futures and let them be handled by the Application Thread when the Task terminates?
As the exceptions will do what i want and terminate the thread, while providing extra information as to why the thread stopped to the application thread so i can show an appropriate alert.
The other reason I want to do this is within the Futures I need access to values from the Task thread, but i don't need to alter them so I'd like to make values final and create the Futures in lambdas. The try-catch blocks are complicating matters as i can't make as many values final (or effectively final) as I'd like. This is because I'm assigning the return values from methods that could potentially throw when i initialise them. As a result I have to surround the assignment in a try-catch, thus need to keep creating temp variables before copying them to a final variable, which makes the process look a mess and likely wastes memory.
Is not catching exceptions inside a Task or Future a good idea or not? Are there any major pitfalls or issues with not catching exceptions until the Application Thread?
Here's an example of what i currently have in my controller class to deal with the event that should trigger this process:
ExecutorService converterExecutor = Executors.newSingleThreadExecutor();
ConverterTask converterThread = new ConverterTask()
converterExecutor.execute(converterThread);
Boolean success = null;
try
{
success = converterThread.get();
}
catch (InterruptedException | ExecutionException e1)
{
e1.printStackTrace();
return false;
}
if (success == null)
{
return false;
}
And the ConverterTask class containing the long-running logic to me run in another thread
public class ConverterTask extends Task< Boolean >
{
public Boolean call() throws Exception
{
//do stuff
ExecutorService executor = Executors.newSingleThreadExecutor();
Future< String > skeletonThread = executor.submit(new Callable< String >()
{
//stuff that can throw exceptions
});
//do more stuff
String temp_sklData = null;
try
{
temp_sklData = skeletonThread.get();
}
catch (InterruptedException | ExecutionException e1)
{
e1.printStackTrace();
return false;
}
if (temp_sklData == null)
{
return false;
}
final String sklData = temp_sklData;
//do more stuff including use sklData in a Lambda Future
}
}
and what I'd like to do in converterTask instead if my propagating the exceptions is a good idea
public class converterTask extends Task< Boolean >
{
public Boolean call() throws Exception
{
//do stuff
ExecutorService executor = Executors.newSingleThreadExecutor();
Future< String > skeletonThread = executor.submit(new Callable< String >()
{
//stuff that can throw exceptions
});
//do more stuff
final String sklData = skeletonThread.get();
//do more stuff including use sklData in a Lambda Future
}
}
I don't really understand the structure of your code, for reasons pointed out by others in the comments. But the basic answer to your question is that you should use try-catch if you can handle the exceptions gracefully (this typically means you can still return a meaningful result), and let them propagate if not.
So a ConverterTask that converted one String into another, which may potentially throw exceptions which prevent the conversion from taking place, would look like
public class ConverterTask extends Task<String> {
private final String textToConvert ;
public ConverterTask(String textToConvert) {
this.textToConvert = textToConvert ;
}
#Override
public String call() throws Exception {
String result = doConversion(textToConvert); // may throw exception...
return result ;
}
}
and a typical usage would be
Executor conversionExec = ... ;
// ...
ConverterTask converterTask = new ConverterTask(someText);
converterTask.setOnSucceeded(e -> {
String result = converterTask.getValue();
// process result...
});
converterTask.setOnFailed(e -> {
// code to execute in case of unhandled exception...
// note you can get the exception with
Throwable thingThatWentWrong = converterTask.getException();
// ...
});
conversionExec.execute(converterTask);
Note that the code in either handler (onSucceeded or onFailed) is executed on the FX Application Thread for you, so you should not block in those methods, but you can access UI elements.
If you had exceptions from which you could recover you would do something along the lines of
#Override
public String call() {
try {
String result = doConversion(textToConvert);
return result ;
} catch (Exception e) {
// fallback computation that doesn't throw exception...
String result = doSafeConversion(textToConvert);
return result ;
}
}
and then you don't need the onFailed handler.
And obviously if you have some recoverable exceptions and some non-recoverable, you can combine the two techniques:
#Override
public String call() throws Exception {
String partialResult ;
// recoverable:
try {
partialResult = doSomeProcessing(textToConvert);
} catch (Exception e) {
partialResult = computeFallbackValue(textToConvert);
}
// non-recoverable: may throw exception which is propagated out
String result = completeComputation(partialResult);
return result ;
}
(and now you need the onFailed handler again).

Java - How to 'return' a value in a class

I am trying to assign a value or return a value in a class. Something like this:
void setOff() {
boolean onValue = true;
Thread t = new Thread(new myClass(onValue));
System.out.println("On: " + onValue);
}
class myClass implements Runnable{
public boolean on;
public myClass (boolean _on) {
on = _on
}
public run() {
on = false;
}
}
Is something like that possible? Thanks!
It is possible, but you need to change your code a bit. Check the following classes:
Callable<V>
FutureTask<V>
The first one is something like a Runnable, but the method you need to implement is defined as V call() throws Exception, instead of void run(): it allows you to return a value.
The second one wraps a Callable<V> (or a Runnable plus a constant return value), and is a Runnable itself, so you can pass it to a Thread just like you were doing with your Runnable.
So, you could change your code to something like the following:
void setOff() {
final FutureTask<Boolean> ft = new FutureTask<Boolean>(new myClass());
new Thread(ft).start();
try {
System.out.println("The result is: " + ft.get());
} catch (ExecutionException e) {
System.err.println("A method executed on the background thread has thrown an exception");
e.getCause().printStackTrack();
}
}
class myClass implements Callable<Boolean> {
#Override public Boolean call() throws Exception {
// let's fake some long running computation:
Thread.sleep(1000);
return true;
}
}
The call ft.get() will only return after the call() method finishes executing (on the background thread), so you will have to wait 1 second before the line gets printed to the console.
There are many other useful methods on FutureTask. Check the documentation.
There are some other classes that you may find useful: ExecutorService and its implementations, and the factory methods in Executors. It has a method called submit which accepts a Runnable or a Callable<V>, and returns a Future<?> or Future<V>, which is one of the interfaces implemented by FutureTask. You get a similar behaviour. For example:
public static void main() {
final ExecutorService es = Executors.newCachedThreadPool();
final Future<Boolean> f = es.submit(new myClass());
try {
System.out.println("The result is: " + f.get());
} catch (ExecutionException e) {
System.err.println("A method executed on the background thread has thrown an exception");
e.getCause().printStackTrack();
}
es.shutdown();
}
The advantage of this is that the ExecutorService will manage the threads for you. It may create some threads and reuse them for the Callables and Runnables you submit: this will possibly improve performance if you have many such jobs, since you will avoid creating one thread per job -- thread creation has some overhead!
EDIT: the .get() method throws an ExecutionException, which wraps an exception that might get thrown during the execution of the .call() method. To inspect the exception, catch the ExecutionException and call .getCause() on it. I've just added the missing try/catch block.

Categories

Resources