how to shut down a thread from a different one? - java

In my application each request has its own thread. I use JMX/JConsole to monitor them, measure the elapsed time. If a a request needs too much time I'd like to stop it by interrupting the underlying thread.
In a method that I call from JConsole I iterate over the list of threads and call interrupt() on the right instance.
However simply calling the interrupt() method on the thread instance only sets a flag, so I need to throw an InterruptedException, too.
But this InterruptedException will apply to currentThread instead of the thread I actually want to stop. Any hint how to shut down the flagged thread?
while (iterator.hasNext()) {
RequestHolder rh = iterator.next();
if (rh.getThread().getId() == threadId) {
rh.getThread().interrupt();
if(rh.getThread().isInterrupted()){
throw new InterruptedException();
}
}
}

But this InterruptedException will apply to currentThread instead of the thread I actually want to stop.
You can check the interruption status of any thread using isInterrupted. However, it is not recommended as a black-boxed approach if you don't know how and when the interruption gets consumed.
Any hint how to shut down the flagged thread?
You cannot cleanly shutdown a thread from another thread.
But it is very simple. In the threads that are running, check for Interruption regularly, such as in loop catch InterruptedException for blocking functions. When you see the interruption in the thread, make it terminate itself. In a sense, the Threads implement their own termination policy.

There is no benefit to throwing InterruptedException. Your if (rh.getThread().isInterrupted()) block can be removed.
Each thread must monitor its own interrupted state, and must exit gracefully when it sees that it has been interrupted.
Usually the code looks something like this:
try {
InputStream in = socket.getInputStream();
while (in.read(buffer) >= 0) {
if (Thread.interrupted()) {
logger.log(Level.FINE, "Interrupted; exiting");
break;
}
// Process request buffer here
}
} catch (InterruptedIOException e) {
logger.log(Level.FINE, "Interrupted; exiting", e);
}
If you are using Channels, you'll want to catch ClosedByInterruptException as well.

you can pass the reference of the thread to be terminated in the constructor of the thread responsible for performing the termination of the first one. Then you can destroy the thread using its reference from another thread.

Related

ExecutorService awaitTermination shutdown signal in the Runnable instance

I've a few questions around ExecutorService and the shutdown process.
My use case:
I use an ExecutorService to spawn a fixed number of threads whose run method look like this:
while (true) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
These threads run infinitely, polling for messages.
What am I trying to do?
I am polling an SQS queue for messages and processing them.
Obviously, in my case, the ExecutorService's shutdown method would not work. When shutdownNow() is called, all my threads are shutdown unceremoniously. I hate it!
Is there a way to invoke awaitTermination and verify, in my Runnable instance(in a finally block?), if shutdown has been initiated and trigger the same for the current thread?
UPDATE: I've refactored my code to perform polling and then spawning threads to process them. Thus, the Runnable instance's run method need not be an endless loop. And awaiTermination will lead to a definite closure of the threads. And to be sure, I've triggered shutdownNow after awaitTermination.
I think what you are doing is conceptually wrong.
awaitTermination is meant to wait for all threads to finish naturally and then stop the executor. When submitting a Runnable, it shouldn't have an idea of the context of it's execution, so, coupling your runnable to your executor is not a good idea IMHO.
Maybe you should look into the Future class and move your Runnable implementation there. Then you will be forced to implement a cancel(boolean) method which you might find useful.
What is exactly your use case? Maybe if you explain it, the community can point out a better suited implementation.
For infinitely running Runnables I rely on catching an InterruptedException, which will typically be thrown from my calling shutdownNow() or occasionally from calling Future#cancel(true)
while(!Thread.interrupted()) {
try {
} catch(InterruptedException e) {
break;
} catch(Throwable e) {
// Keeping the thread alive despite exception
}
}
// Thread was interrupted via shutdownNow(), cleanup resources
If I need to distinguish between a resumable interrupt and a shutdown interrupt then I share an AtomicBoolean doShutdown among my Runnables that is initialized to false and set to true if I want an InterruptedException to terminate the thread.
You have to check the interrupt status of the thread you are running in (see tutorial on interrupts here: https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html). Your code should be:
while (!Thread.currentThread().isInterrupted()) {
try {
this.currentThreadRunning = true;
processMessage();
}
catch (Throwable e) {
// Keeping the thread alive despite exceptions.
}
}
Note however that you do have to handle interrupts correctly in code called from your runnable. If there is anything like the following:
try {
// do something
} catch(InterruptedException e) {
// ignore
}
then this won't work. The correct way to handle InterruptedException is to call Thread.currentThread().interrupt();.
You should not call shutdownNow() But you should only call shutdown and use awaitTermination to wait for some time.
So shutdown would be something like this
Declare a volatile variable
private volatile stopThread = false;
On shutdown you call
this.stopThread = true;
executor.shutdown();
executor.awaitTermination(..
executor.shutdownNow() // in case termination takes too long
And in the thread you check for the stopThread variable. You cannot use isInterrupted here because we are not interrupting the thread. we are just waiting for the thread to exit based on this condition
if(stopThread){
// calling off all the operations and returning
}
I have written an article about shuting down the executorservice properly
http://programtalk.com/java/executorservice-not-shutting-down/
I hope this will help you.

How do I interrupt a thread given a Future object?

I want to start a thread and cancel it if it doesn't finish within 5 seconds:
private final class HelloWorker implements Callable<String> {
public String call() throws Exception {
while(true) {
if (Thread.isInterrupted()) {
return null;
}
}
return performExpensiveComputation();
}
private String performExpensiveComputation() {
// some blocking expensive computation that may or may not take a very long time
}
}
private ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
Future<String> future = executorService.submit(new HelloWorker());
try {
String s = future.get(5, TimeUnit.SECONDS);
} catch (TimeoutException e) {
future.cancel(true);
System.out.println("cancelled: " + future.isCancelled() + "done: " + future.isDone());
executorService.shutdown();
try {
System.out.println("try to terminate: " + executorService.awaitTermination(60, TimeUnit.SECONDS));
} catch (Exception ex) {
// ignore
}
}
However it looks like the awaitTermination returns false. Is there a way for me to check why an ExecutorService won't terminate? Can I figure out what threads are still running?
There is no safe way to stop a running thread without disturbing the stability of the rest of the process. This is why Thread#stop has been deprecated a long time ago, and why Executor Services only use the soft, cooperative Thread#interrupt mechanism.
Your thread will have to actively check if an interrupt has been requested and perform proper cleanup before ending. Alternatively, the thread will call some interruptible JDK methods, which will throw InterruptedException, which the tread will properly honor and end itself.
Why Future.cancel() doesn't work the way you think it does
Future cancel removes the task from the running queue. If your task is already running it won't stop it. So cancel() is a different concept that interrupting. As the Javadocs say:
Attempts to cancel execution of this task. This attempt will fail if
the task has already completed, has already been cancelled, or could
not be cancelled for some other reason. If successful, and this task
has not started when cancel is called, this task should never run. If
the task has already started, then the mayInterruptIfRunning parameter
determines whether the thread executing this task should be
interrupted in an attempt to stop the task.
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/concurrent/Future.html#cancel(boolean)
What you are asking is how to interrupt. Fortunately, when you call Future.cancel() it will call the interrupt method. But you'll need to allow it with the mayInterruptIfRunning flag and will need to handle interrupts correctly (see below).
Why interrupt?
Interrupting threads in Java is useful when you have a long running task that you now need to stop, or when you have a daemon that you need to turn off, and other examples.
How to interrupt
To interrupt you call interrupt() on the thread. This is a cooperative process, so your code has to be ready for it. Like this:
myThread.interrupt();
Responsible code
Your code's responsibility is to be ready for any interruptions. I'd go so far to say that whenever you have a long running task, that you insert some interrupt ready code like this:
while (... something long...) {
... do something long
if (Thread.interrupted()) {
... stop doing what I'm doing...
}
}
How to stop what I'm doing?
You have several options:
If your you are in Runnable.run() just return or break out of the loop and finish the method.
You may be in some other method deep in the code. It may make sense at that point for that method to throw InterruptedException so you would just do that (leaving the flag cleared).
But maybe deep in your code it doesn't make sense to throw InterruptedException. In that case you should throw some other exception, but before that mark your thread interrupted again so the code that catches knows that an interrupt was in progress. Here's an example:
private void someMethodDeepDown() {
while (.. long running task .. ) {
... do lots of work ...
if (Thread.interrupted()) {
// oh no! an interrupt!
Thread.currentThread().interrupt();
throw new SomeOtherException();
}
}
}
Now the exception can propagate an either terminate the thread or be caught, but the receiving code hopefully notices that an interrupt is in progress.
Should I use isInterrupted() or interrupted()
You should prefer interrupted() because:
Your code should reset the interrupt flag because if you don't the thread you are using could go back to a thread pool with an interrupted state causing problems (of course, that's a bug in the thread pool code, you won't get that behavior if you use Executors.newFixedThreadPool() for example. But other threading code could have it.
As another answer stated, the clearing of the interrupted flag indicates that you've received the message and are taking action. If you leave it on true, the after a while caller can assume you won't respond to it in a timely manner.
Why interrupt() why not some other flag in my code?
Interrupt is the best mechanism for interruption because our code can be ready for it. If we find code that is just catching and ignoring the InterruptExceptions or not checking for interrupted() in its body then we can correct those mistakes and make our code always cleanly interruptible without creating arcane dependencies on non-standard mechanisms in your code.
Unfortunately Joshua Block proposed the opposite in his famous book Effective Java, Second Edition. But enabling the interrupt() method to work as intended is much better, because this code is used by the Java standard library as explained above. A custom interruption method would not be.

java ensure completion of a thread without interruption

I have many threads running, but I want to execute a particular thread (a TimerTask's run() method) to run to its completion and I don't want any interruption by any other threads.
I think synchronized(this) { } wont ensure its completion.
Please suggest me a correct way to do this.
You can catch InterruptedException and set interrupt status once your work is completed.
Noncancelable tasks
Some tasks simply refuse to be interrupted, making them noncancelable. However, even noncancelable tasks should attempt to preserve the interrupted status in case code higher up on the call stack wants to act on the interruption after the noncancelable task completes. Listing 6 shows a method that waits on a blocking queue until an item is available, regardless of whether it is interrupted. To be a good citizen, it restores the interrupted status in a finally block after it is finished, so as not to deprive callers of the interruption request. (It can't restore the interrupted status earlier, as it would cause an infinite loop -- BlockingQueue.take() could poll the interrupted status immediately on entry and throws InterruptedException if it finds the interrupted status set.)
public Task getNextTask(BlockingQueue<Task> queue) {
boolean interrupted = false;
try {
while (true) {
try {
return queue.take();
} catch (InterruptedException e) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted)
Thread.currentThread().interrupt();
}
}
In general you can't prevent a Thread to be "interrupted" but this does not mean that the computation will be cancelled; just that any sleep/wait operations will throw an Exception.
See javadoc.
If you don't want to exit then, you can catch the InterruptedException and swallow it.
'Actually one critical thread which I want to run to its completion
does not do so, logs suggest other threads are getting their
time-slices and the critical does not continue afterwards.'
This does not sound at all like an OS scheduling problem. It sounds much more like the 'critical thread' is getting blocked or has exited because of some exception.
Repetitive runs suggest that the critical thread stops in different
point of execution
sounds more exceptionny than blocky.
If I'm wrong, and your critical thread is getting preempted because there are more ready threads than cores, you should raise the priority of your critical thread so that it does not get preempted, (or just reduce the loading on the box:).
The only other possibility is that your thread is using a huge amount of data and you're getting a lot of page-faults. In this case, get more RAM, an SSD, or both!

How to suspend thread using thread's id?

Code which I am trying
public void killJob(String thread_id)throws RemoteException{
Thread t1 = new Thread(a);
t1.suspend();
}
How can we suspend/pause thread based on its id?
Thread.suspend is deprecated,There must be some alternative to achieve this.
I have thread id I want to suspend and kill the thread.
Edit: I used this.
AcQueryExecutor a=new AcQueryExecutor(thread_id_id);
Thread t1 = new Thread(a);
t1.interrupt();
while (t1.isInterrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
t1.interrupt();
return;
}
}
But I am not able to stop this thread.
How can we suspend/pause thread based on its id? ... I have thread id I want to suspend and kill the thread.
The right way to kill a thread these days is to interrupt() it. That sets the Thread.isInterrupted() to true and causes wait(), sleep(), and a couple other methods to throw InterruptedException.
Inside of your thread code, you should be doing something like the following which checks to make sure that it has not been interrupted.
// run our thread while we have not been interrupted
while (!Thread.currentThread().isInterrupted()) {
// do your thread processing code ...
}
Here's an example of how to handle interrupted exception inside of a thread:
try {
Thread.sleep(...);
} catch (InterruptedException e) {
// always good practice because throwing the exception clears the flag
Thread.currentThread().interrupt();
// most likely we should stop the thread if we are interrupted
return;
}
The right way to suspend a thread is a bit harder. You could set some sort of volatile boolean suspended flag for the thread that it would pay attention to. You could also use object.wait() to suspend a thread and then object.notify() to start it running again.
I posted a PauseableThread implementation recently that uses a ReadWriteLock internally. Use one of these or a variant and you should be able to pause your threads.
As to pausing them by id, a little googling suggests a way to iterate over all threads which looks like it should work. Thread has exposed a getId method for some time.
Killing the thread is different. #Gray has neatly covered that one.

Program continues to run despite InterruptedException

I started learning java and I am now at the concurrency chapter. After reading some stuff about concurrency I tried an example of my own.
public class Task implements Runnable{
public void run() {
while(!Thread.interrupted()) {
try {
System.out.println("task");
TimeUnit.SECONDS.sleep(2);
}catch (InterruptedException e) {
System.out.println("interrupted");
}
}
}
}
public static void main(String[] args) throws Exception {
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(new Task());
TimeUnit.SECONDS.sleep(10);
exec.shutdownNow();
}
The problem is that i was expecting to see the following output:
task
task
task
task
task
interrupted
but after I get this, the program continues printing until I close it.
So, my question is what am I doing wrong? why does the program continues printing?
When you shutdown the executor, it tries to stop its running tasks by interrupting them. This causes an InterruptedException to be thrown, but you just swallow it and continue. You should return in your catch clause, and/or reset the interrupted status of the thread by calling Thread.currentThread.interrupt(), which will reset the interrupted status and exit the loop.
The section about interrupts in the Java tutorials about concurrency explain the problem quite well:
The Interrupt Status Flag
The interrupt mechanism is implemented using
an internal flag known as the interrupt status. Invoking
Thread.interrupt sets this flag. When a thread checks for an interrupt
by invoking the static method Thread.interrupted, interrupt status is
cleared. The non-static isInterrupted method, which is used by one
thread to query the interrupt status of another, does not change the
interrupt status flag.
By convention, any method that exits by throwing an
InterruptedException clears interrupt status when it does so. However,
it's always possible that interrupt status will immediately be set
again, by another thread invoking interrupt.
So when you catch the InterruptedException within the loop, the interrupted status is already reset and thus, the next call of Thread.interrupted() will return false, which in turn keeps the while loop running. To stop the loop, you have the following options:
Use break to exit the loop
Use return to exit the whole method
Move the try-catch-block to outside the while loop (as suggested by Nathan Hughes)
Call interrupt() on the current thread to set the interrupted flag again
Use a separate boolean to control the loop and set that flag accordingly in the catch-block
Make the task a recurring task by using a ScheduledExecutorService and dropping the loop from the run-method of your Runnable
You're still in the while loop, add a break or some other way out of the loop.
catch (InterruptedException e) {
System.out.println("interrupted");
break;
}
Threading in Java is kind of a cooperative activity, you've been asked to stop, but you need to be polite enough to actually do it. This allows the thread time to tidy its affairs before its demise.
As is explained in detail by Simon and Amir, your loop termination condition is surprisingly not sufficient.
"There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so if any tasks mask or fail to respond to interrupts, they may never terminate."
source : http://download.oracle.com/javase/1,5.0/docs/api/java/util/concurrent/ExecutorService.html#shutdownNow()

Categories

Resources