java ensure completion of a thread without interruption - java

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!

Related

How the main thread sleep/interrupt works in following code

How the second loop actually interrupts the sleeping main thread, and first does not??
My understanding is after Thread.sleep(3000), the code Thread.currentThread().interrupt() will be executed after 3 seconds.
Can anyone explain how it actually works
for (int i = 0; i < 2; i++) {
try {
System.out.println("loop : " + i);
Thread.sleep(3000);
System.out.println("Woke up");
Thread.currentThread().interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
loop : 0
Woke up
loop : 1
java.lang.InterruptedException: sleep interrupted
exception loop:1
at java.base/java.lang.Thread.sleep(Native Method)
at multithreadings.Mainclass.main(Mainclass.java:13)
Interruption is a polite request to stop: a Thread is under no obligation to stop.
It's like the Robin Williams joke about what police in the UK say when you commit a crime:
Stop! Or I'll say stop again!
Also, interrupting a thread doesn't cause an InterruptedException to be thrown: it merely sets a flag on the thread. If something (like Thread.sleep) checks this flag, and finds that it is set, it may then throw an InterruptedException; but the flag and exception are two orthogonal ways of indicating interruption.
As such:
On the first execution, you sleep for 3 seconds, then set the interrupted flag, and the loop body finishes normally.
On the second execution, you ask to sleep for 3 seconds, but Thread.sleep detects the interrupted flag, and throws the exception.
There is a single thread involved in the code you posted. This thread executes a loop. At the first iteration, the thread interrupts itself. Interrupting doesn't mean "stop executing immediately". It means: "please, I would like you to stop running when you can".
A thread that wants to respect interruption requests can do it in two ways:
It regularly checks if it has been interrupted, and if it's the case, then it stops executing (by breaking out of a loop or returning, for example)
It calls a blocking method such as sleep(), which will throw an InterruptedException if the thread has been interrupted or is being interrupted.
What happens is the second case. A request for interruption is done in the first iteration, after the call to sleep(). The thread continues running, and at the second iteration, it calls sleep(), which throws en InterruptedException because the thread has been interrupted before.
In Java, one thread cannot stop the other thread. A thread can only request the other thread to stop. The request is made in the form of an interruption. Calling the interrupt() method on an instance of a Thread sets the interrupt status state as true on the instance.
All blocking methods respond to interruption by throwing InterruptedException once the interrupt status is set to true. , if you want to check more in detail, please read the below article. See how Thread Interruption works in Java.
Read the documentation, i.e. the javadoc of interrupt():
Interrupts this thread.
Unless the current thread is interrupting itself, which is always permitted, ...
If this thread is blocked ...
If this thread is blocked ...
If this thread is blocked ...
If none of the previous conditions hold then this thread's interrupt status will be set.
and sleep(long millis):
Throws InterruptedException if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
Since the thread has already interrupted itself on the second iteration of the loop, thereby setting it's own interrupted status, the sleep(...) method is immediately interrupted.

How to stop / kill multiple threads after a Time-Out value in java

I want to stop / kill all Threads (Runnables) started by Main after a given timeout. I tried to do as mentioned below. But it is not working as expected. Apart from that, I tried with the Thread.interrupt() but the results is negative. I tried thread.stop(). It is working but deprecated.
Can anyone give some idea on this?
Note : I'm focusing on a solution for Runnables not Callables. And I'm trying to do this bymodifying only the client code (Main). Not the Threads (Supplier)
Main
Thread roxtoursThrd = new Thread(new Supplier("roxtours", 1));
Thread bluevacationsThrd = new Thread(new Supplier("bluevacations", 1));
Thread elixerThrd = new Thread(new Supplier("elixer", 1));
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
taskExecutor.execute(roxtoursThrd);
taskExecutor.execute(bluevacationsThrd);
taskExecutor.execute(elixerThrd);
taskExecutor.shutdown();
// taskExecutor.shutdownNow(); // This is also not stopping threads. They continue.
try {
taskExecutor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
Supplier.java
public class Supplier implements Runnable {
public Supplier(String name, int count) {
this.name = name;
this.count = count;
}
#Override
public void run() {
try {
// Some time consuming operations (URL Connections, XML Decoding, DB Queries etc etc) are goes in here.
} catch (Exception e) {
e.printStackTrace();
}
}
String name = null;
int count = 0;
Logger logger = Logger.getLogger(Supplier.class);
}
Making the executor's tasks respond to interruption will require changing the code for the Suppliers. Interruption is cooperative; the thread being interrupted gets a flag set on it, but it's up to the thread to decide how to handle it. If your Runnable doesn't act on it, as in your example, then nothing happens, the thread just keeps on executing.
The Executor can only cancel threads that respond to interruption, see the API documentation for ExecutorService.shutdownNow:
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.
A thread can check its flag with the Thread#isInterrupted method. Your Runnable task should check Thread.getCurrentThread().isInterrupted().
If a thread is waiting or sleeping when the interrupted flag is set then an InterruptedException will be thrown and the flag will be cleared.
Do not use Thread#setDaemon(true) unless you're prepared for those threads to disappear suddenly with no warning and no chance to clean up pending tasks when the rest of the application shuts down.
The other option is the deprecated Thread#stop method, which causes ThreadDeath to be thrown. Unlike interruption, this is not cooperative, and it's between difficult and impossible to write code that can predictably and cleanly terminate when this exception occurs, because ThreadDeath can be thrown anywhere, unlike InterruptedException, which is much more manageable since it is only thrown from specific blocking calls.
Use shutdownNow() instead of shutdown().
The shutdown() will initiate the shutdown and it will not accept any new tasks but you never know when the threads will be actually stopped.
The shutdownNow() will immediately attempts to stop all the active threads and this will return all the active threads which are awaiting for execution.
Again there is no guarantee that all the threads will be stopped immediately (Threads will go for a graceful shutdown and it may take time based on the task given to the thread). We have to use either of the below methods to wait till all the threads are completed its execution.
executor.awaitTermination(...);
or
while (! executor.isTerminated()) {
// Sleep for few milliseconds...
}
Refer the doc: http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html#shutdown%28%29
Your thread's run method is not blocking, hence it does not run into a situation where an InterruptedException is thrown.
When a Thread is inerrupted, besides throwing an exception if it is blocking, it also has its interrupted status set, that is to say the method Thread#isInterrupted() returns true. Also, the method Thread#interrupted also returns true, but with the latter the interrupted status of the thread is cleared.
In your example you are not blocking nor are you checking the threads inerrupted status.
EDIT: Since you are not checking to see if the thread is interupted nor are you blocking, then you can't stop the threads explicitly, but you can stop them by making them daemon threads and then when your main thread (which is a user thread) finishes, all the other daemon threads will stop. Main difference between daemon thread and user thread is that as soon as all user thread finish execution java program or JVM terminates itself, JVM doesn't wait for daemon thread to finish there execution.
If you want to interrupt threads, you have to provide interruption entrance point. Sleep for a very short time, for example, then catch and handle InterruptionException.
Next what you can do is make use of isInterrupted() method in every iteration and the handle that as well.
Other approach would be to make all the threads daemons with setDaemon(), as they would be killed after main thread finishes, but this would be useful only if main was to be stopped.
In response to your edit/updated question:
excerpt from shutdownNow() documentation
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.
So either you prepare you application to work as multi-threaded or you stick to single thread.
Also, see How do you kill a thread in Java?.
And the most important link from the question above: http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html

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.

how to shut down a thread from a different one?

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.

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