I have a Java class which starts a TimerTask in its main method, the class extending TimerTask is an inner class (Class myTimer extends TimerTask). In its run method myTimer throws an exception, In the main method I am trying to catch the exception like this:
try {
timer.schedule(new myTimer(arg1, arg2), 0, RETRY_PERIOD);
} catch (Exception e) {
System.out.println("Exception caught");
}
But this doesn't work, it never catches the exception, myTimer thread throws. Any ideas how to do that ?
Your situation is a bit tricky and I'm not sure what you expect to happen in your code snippet. Do you expect the main thread to block until the timer thread throws an exception? Because that will not happen. The only thing that try-catch will do is catch exceptions occurring in the call to schedule, not in the code executed by the thread periodically.
It would not make sense anyway. Since a timer thread can throw an exception in parallel with the main thread, you would need to either freeze the main thread periodically to check for exceptions or freeze it permanently until the timer finishes.
The latter case can be easily done with a ScheduledThreadPoolExecutor:
ScheduledThreadPoolExecutor exec = new ScheduledThreadPoolExecutor(1);
ScheduledFuture f = exec.scheduleWithFixedDelay(new Task(arg1, arg2), 0,
RETRY_PERIOD, TimeUnit.MILLISECONDS);
...
try {
f.get(); // wait for task to finish
} catch(ExecutionException ex) {
System.out.println("Exception caught");
}
where Task is a class that implements Runnable.
Of course, this will block the main thread until the task returns or throws an exception (which might never happen). Alternatively you can use the timed get to check periodically for exceptions.
The Timer will be executing the TimerTask.run() method in a different thread from the the thread that added it, the main method the parent class will not able to catch the thrown exception.
A possible solution would be to prevent the exception from propagating out of the run() method and make any useful information available to the parent via some query method. The parent would be required to wait for the run() method to complete before querying for the result.
Related
I am currently running a Thread from a Service to do some background work.
Now there is the possibility that the Thread crashes or I want to
interrupt the thread from the Service. So how am I supposed to:
stop the Thread realiable, (hard)
catch exceptions and call the Service about the crash
handle InterruptedException if interrupted while sleep()
is Thread.isInterrupted a good way to detect if the Thread stopped?
What I have done so far is the following:
#Override
public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {
doMyBackgroundWork();
sleep();
}
}catch(Exception e){
ExceptionHandler.logAndSendException(e);
Thread.currentThread().interrupt();
if(crashedListener != null){
crashedListener.onThreadCrashed();
}
}
LOG.i("Thread stops now.");
}
private void sleep() {
try {
sleep(frequency);
} catch (InterruptedException e) {
//what to do here? it can happen because I stopped it myself
}
}
So at first I am running my Thread until it gets interrupted.
If any exception occurs, I want to start a new Thread, therefore
my Service implements a listener interface and I call it, once an
Exception is thrown. I know that catching everything is discouraged,
but I need to know if the Thread stops, without polling Thread.isAlive()
all the time.
Additionally to my four questions above:
is my code reliable and does what I need?
is it ok to call interrupt on the Thread itself?
Thanks!
You are not actually interrupting your own thread because the catch block is outside of the while loop. Therefore, any exception would stop execution immediately.
Interruption is essentially just a request (usually from another thread) to stop doing what you are doing. The thread is free to ignore it and keep doing what it is doing. Normally you have to throw an exception in response to an interrupt, or stop execution some other way such as just breaking from the loop (you need this around the //what to do here? comment). It so happens that some library methods are "responsive to interruption" meaning they will throw an exception if the thread is ever interrupted, such as Thread.sleep(), which you will most likely have in your sleep call.
I recommend picking Java Concurrency In Practice. Among the excellent concurrency material, there is a chapter on interrupts which is very helpful.
EDIT:
I would remove the code where you interrupt your own thread. You will also need to rethrow the InterruptedException as a runtime exception to get out of the execution loop. Usually people will create a new Exception that extends RuntimeException that is something like MyInterruptedException. You can then add it to the catch block around your loop so that you know when the thread was interrupted vs execution failed.
As a general example you can do something like this:
public void run() {
try {
while (true) {
// check for interrupts in the loop, or somewhere in the work method
if (Thread.interrupted()) {
throw new MyInterruptedException("Important thread interrupted.");
}
doMyBackgroundWork();
sleep();
}
}
catch(Exception e){
ExceptionHandler.logAndSendException(e);
if(crashedListener != null){
crashedListener.onThreadCrashed();
}
}
catch(MyInterruptedException i) {
LOG.i("Execution stopping because of interrupt.");
}
}
private void sleep() {
try {
sleep(frequency);
} catch (InterruptedException e) {
throw new MyInterrptedException(e);
}
}
we have a nice and effective method called stop()(Thread.stop(void):void) which is deprecated, but it works and it's lovely.
Note that stop() throws ThreadDeath at the target thread which is not an exception(and it could any other throwable too), but an Error, so your code will not catch any signal about this.
public void run() {
try {
while (<<using_a_volatile_bool_type_is_better>>) {
...
}
}catch(Throwable t){/**/}/*use throwable instead of exception.*/}
}
Beside dear friend stop() we also have pause() method too, and it really pauses the target thread.
Not just one solution out there, but if it's really critical to keep thread run and run the emergency(or itself) just after any crash, you may run it as a separately app/process, plus get progress status(if any) that ensures you the target thread/app is not freezed(blocked,...)
In java, I have ExecutorService that runs with while true, and Throwable catch clouse. I find out that from time to time the thread goes down. That means the system stop function.
So my question is, first of all, how can I catch the "thread killed" event (in order to send me email on such case)?
Also, how can this thread goes down?
the code is:
ExecutorService changesTrackerThread = Executors.newSingleThreadExecutor();
changesTrackerThread.submit(queueUpdater());
private Runnable queueUpdater() {
return new Runnable() {
#Override
public void run() {
while (true)
{
try
{
// do some code, then sleep
Thread.sleep(2000L);
} catch (Throwable t)
{
_log.error("something bad happened, but the loop should keep running", t);
}
}
}
};
Well first of all, why are you using a while loop here!?
You should use a scheduled executor:
ExecutorService changesTrackerThread = Executors.newSingleThreadScheduledExecutor()();
changesTrackerThread.scheduleAtFixedRate(new queueUpdater(), 0, 2, TimeUnit.SECONDS);
private Runnable queueUpdater() {
return new Runnable() {
#Override
public void run() {
try
{
// do some code
} catch (Throwable t)
{
_log.error("something bad happened", t);
}
}
};
I do not know why your thread dies, show us the full code.
But this way even if the thread dies the Excecutor will rerun it after the given period(2 seconds in this example.
As others have noted, you could replace your while (true) and sleep() loop with a ScheduledExecutorService. Scheduling a repeating task on such a service will return a ScheduledFuture which you can use to check the status of this task or to cancel it if you have a need for that. This will enable you to remove the try/catch block from the code.
Start the service like this:
ScheduledExecutorService svc = Executors.newScheduledThreadPool(1);
I would use newScheduledThreadPool() instead of newSingleThreadScheduledExecutor() since the former will restart threads if necessary.
Then, schedule the work like this:
void doSomeCode() {
// do some code
}
ScheduledFuture<?> sf = svc.scheduleAtFixedRate(this::doSomeCode, 0L, 2L, TimeUnit.SECONDS);
(Or if you wish you can inline doSomeCode() as a lambda or an anonymous inner class.)
Now what happens if the task fails with an exception? The ScheduledFuture object returned allows you to check status in a variety of ways. If you have a thread that you can dedicate to waiting for failures, you can have it call sf.get() which will throw an ExecutionException that wraps the exception that caused the task to fail. Otherwise, it blocks indefinitely. ScheduledFuture.get() is a bit weird in that unlike an ordinary Future.get() call, it never returns a value; it always throws an exception.
When/if the task fails, the caller of sf.get() can log the exception and resubmit the task, or whatever. If you don't want to block a thread indefinitely, you can poll for failure using sf.isDone() or sf.get(0L, TimeUnit.SECONDS). Note that both overloads of sf.get() communicate all of their return information via the type of a thrown exception, which may make them somewhat inconvenient to use.
You could put exception handling within the task itself, catching Throwable and continuing no matter what, and this will probably work. It does bake the logging/restart/resubmission policy into the task itself, which may be unpleasant. Using ScheduledFuture lets you separate these policies from the actual work performed by the task.
I am trying to interrupt a normally running thread (which is not in sleep() or wait() state) .
while going through in net i got to know interrupting a normally running thread will just set the flag true and continue the process.
Code snippet is
one.java
......
......
actionperformedmethod {
if (actionCmd.equals("cancel")) {
try {
r1.stop(); // to two.java
} catch (InterruptedException ex) {
....
....
}
}
}
in two.java
.....
.....
stop method() throws InterruptedException{
if(!(t.isInterrupted())){
t.interrupt();
throw new InterruptedException();
}
}
from two.java when i throw InterruptedException i can able to get the exception block at one.java , but how do i stop the thread after that because even after that thread seems to continue the normal process.
Am new to thread concepts please help..
The interrupt() method is co-operative rather than pre-emptive - the background task needs to actively check Thread.interrupted() at suitable intervals, and take action to shut itself down cleanly.
public void run() {
openSomeResources();
try {
while(notFinished) {
if(Thread.interrupted()) return;
doSomeStuff();
}
} finally {
closeTheResources();
}
}
In this example if the thread is interrupted in the middle of doSomeStuff() then it will complete the current "iteration" before responding to the interruption. Getting the correct balance between responding promptly to an interrupt on the one hand, and responding only at a safe point in the execution on the other hand, is something that is inherently specific to the particular task - there is no one-size-fits-all answer.
Note however that any blocking method that throws an InterruptedException will reset the interrupt flag when this exception is thrown. Therefore in order for this sort of checking to work you must re-interrupt yourself whenever you receive an InterruptedException
try {
Thread.sleep(3000);
} catch(InterruptedException e) {
// we were interrupted - set the flag so the next interrupted() check will
// work correctly.
Thread.currentThread().interrupt();
}
Interrupt will not stop the thread. it just sets the flag to true to signal the thread to stop the execution soon.
to stop the execution
add global variable as
private volatile boolean exit = false;
and
you add one method in your 2nd class
public void requestExit(){
exit = true;
}
inside run () of your thread do something like this
if (exit == true){
return;
}
whenever you want to call just call this method requestExit() from your main() or wherever you want to stop
this is the best way to stop the thread.. using stop() on thread is dangerous as it does not clear any resources and its not advisable to use even by oracle hence deprecated.
let me know for any issues
Threads are only running whilst their run() method is on the stack so usually people put a while(true) inside the run method, all you need to do in you thread to stop it is to return somewhere in the run method or break the loop then as soon as the run() method is no longer running the thread has been stopped.
I am trying to run the following piece of code:
public static void main(String[] args){
ScheduledExecutorService service = new ScheduledThreadPoolExecutor(2);
Runnable r = new Runnable() {
#Override
public void run() {
throw new RuntimeException();
}
};
service.execute(r );
ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
new Thread(r).run();
}
Regarding the above I have the following questions:
Is there any way to catch and respond to exceptions happening on the executor's thread?
Why is the exception from the thread created explicitly propagated to the main thread, but both executions using the executor service does not propagate that error? How can this error ever be discovered?
EDIT: One further question came to mind:
How can i stop a given periodic task that I schedule, let's say after N repeats or N minutes?
Question 2 is really easy - you're not actually starting a new thread, you're just calling run(), which runs synchronously in the original thread. You should be calling start(), at which point the exception won't be propagated back.
As for handling exceptions in a ScheduledExecutorService - if you call Future.get(), it will throw ExecutionException if the original task threw an exception, exposing the original exception as the cause:
Exception thrown when attempting to retrieve the result of a task that aborted by throwing an exception. This exception can be inspected using the Throwable.getCause() method.
If you need to respond to exceptions without blocking for the future to complete, you could wrap your "real" Runnable in another one which just delegated to the original's run() method, but with an appropriate try/catch block.
You can catch it like this:
ScheduledFuture<?> schedule = service.schedule(r, 0, TimeUnit.SECONDS);
try {
Object get = schedule.get();
} catch (InterruptedException ex) {
ex.printStackTrace();
} catch (ExecutionException ex) {
ex.printStackTrace();
}
If the code running in (Scheduled)ExecutorService throws an exception it will be rethrown upon calling Future.get() wrapped into ExecutionException
EDIT:
about stopping scheduled tasks, it has been discussed and solved already.
I am writing an app that will make use of multiple threads. There is main thread that is launching another threads. What i want to acomplish is when one of the launched threads throws an exception, the main thread should stop launching threads. It looks more or less like this:
class SomeClass {
boolean launchNewThread = true;
public static void main() {
while (launchNewThread) {
try {
AnotherClass.run();
} catch (CrossThreadException e) {
launchNewThread = false;
}
}
}
}
class AnotherClass implements Runnable {
public void run() {
if (a=0) throw new CrossThreadException();
}
}
You should do it yourself - catch the exception and pass it somehow into the launching thread.
Also, there is Future concept, which does it already. You should launch your threads as futures and check isDone(), and catch ExecutionException from get(), this exception will be thrown if a future's task thrown an exception.
You can also use a listener as described in How to throw a checked exception from a java thread?
When an exception is thrown inside one of the child threads, you could call a method like listener.setLaunchNewThread(false) from the child thread which will change the value of your boolean flag in the parent thread.
On a side note, calling AnotherClass.run() does not start a new thread but only call the run method from AnotherClass within the same thread. Use new Thread(new AnotherClass()).start() instead.