How to interrupt BlockingQueue? - java

BlockingQueue.put can throw InterruptedException.
How can I cause the queue to be interrupting by throwing this exception?
ArrayBlockingQueue<Param> queue = new ArrayBlockingQueue<Param>(NUMBER_OF_MEMBERS);
...
try {
queue.put(param);
} catch (InterruptedException e) {
Log.w(TAG, "put Interrupted", e);
}
...
// how can I queue.notify?

You need to interrupt the thread that is calling the queue.put(...);. The put(...); call is doing a wait() on some internal condition and if the thread which is calling the put(...) gets interrupted, the wait(...) call will throw InterruptedException which is passed on by the put(...);
// interrupt a thread which causes the put() to throw
thread.interrupt();
To get the thread you can either store it when it is created:
Thread workerThread = new Thread(myRunnable);
...
workerThread.interrupt();
or you can use the Thread.currentThread() method call and store it somewhere for others to use to interrupt.
public class MyRunnable implements Runnable {
public Thread myThread;
public void run() {
myThread = Thread.currentThread();
...
}
public void interruptMe() {
myThread.interrupt();
}
}
Lastly, it is a good pattern when you catch InterruptedException to immediately re-interrupt the thread because when the InterruptedException is thrown, the interrupt status on the thread is cleared.
try {
queue.put(param);
} catch (InterruptedException e) {
// immediately re-interrupt the thread
Thread.currentThread().interrupt();
Log.w(TAG, "put Interrupted", e);
// maybe we should stop the thread here
}

You need to have a reference to the thread running the code with queue.put(), like in this test
Thread t = new Thread() {
public void run() {
BlockingQueue queue = new ArrayBlockingQueue(1);
try {
queue.put(new Object());
queue.put(new Object());
} catch (InterruptedException e) {
e.printStackTrace();
}
};
};
t.start();
Thread.sleep(100);
t.interrupt();

Calling put will wait for a slot to be free before it adds the param and flow can continue.
If you capture the thread that is running when put is called (ie, call Thread t1 = Thread.currentThread() before calling put) and then in another thread call interrupt on this (whilst the t1 is blocked).
This example has something similar whereby it takes care of calling interrupt after a given timeout.

Related

How to stop a thread in java while it is in a waiting state?

Suppose I have one thread named T1 which is holding the lock while other threads T2, T3, T4 are waiting for the lock. Now, I want to stop thread T2, but the other threads T3, T4 should be still waiting. How could I achieve this?
You can use the interrupt() method from the Thread Class something like this
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(someTask());
t.start();
Thread.sleep(3_000);
t.interrupt();
t.join(1_000);
}
private static Runnable someTask() {
return () -> {
for (int i = 0; i < 10; i++) {
System.out.print(i);
try {
Thread.sleep(1_000);
} catch (InterruptedException e) {
break;
}
}
};
}
What you should do is utilize T2.interrupt(). Interrupt will wake up the respective thread and throw an InterruptionException that the thread must handle. From here, you can end the thread. Lets look at a brief example of T2's possible Runnable's run() method below.
public void run() {
while (true) {
try {
doNonBlockingWork(); // Random code logic
doBlockingWork(); // Where the thread will attempt to get and wait for the lock
doMoreCode(); // Will never get here if interrupt is called while waiting for lock above
} catch (InterruptedException e){
Thread.currentThread().interrupt(); // Maintain Interrupt Status
break; // Finish
}
}
}
If another thread, lets say the main thread executes the following code,
public void killSpecificThread() {
doMyLogic();
startThreads(); // All the threads begin
T2.interrupt();
doMoreLogic();
}
T2 will wake up (this works the same as well if it was awake, just no wake up step) and immediately be thrown an InterruptionException. Because of our try catch above, we are able to handle it by finishing the run() method.

Why doesn't Java Thread receive interrupt flag?

I am trying to understand interrupting threads within an ExecutorService and I can't figure out why the following MyNeverEndingRunnable class doesn't get the interrupt signal. I have a class that implements Runnable and simply prints and waits in a loop until it is interrupted:
class MyNeverEndingRunnable
implements Runnable
{
int count = 0;
#Override
public void run()
{
while (true)
{
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
try { Thread.sleep(5000L); } catch (Exception ignored) {}
if (Thread.interrupted())
{
break;
}
}
}
}
I spawn a few of these threads then call shutdownNow() on my ExecutorService which should call interrupt on each of the running threads but the below code continues to run forever:
int threadCount = 5;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
Future[] threads = new Future[threadCount];
for (int k = 0; k < threadCount; ++k)
{
threads[k] = executorService.submit(new MyNeverEndingRunnable());
}
Thread.sleep(20000L);
executorService.shutdownNow();
while (!executorService.isShutdown()) Thread.sleep(1000L);
Does anyone know what I am doing wrong here?
From the Javadoc:
InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown. [My emphasis]
NB There's nothing that actually guarantees that threads are interrupted by shutdownNow(). It just describes that as a 'typical implementation'.
Your code is a little strange. Try this:
try
{
Thread.sleep(5000L);
}
catch (InterruptedException exc)
{
break;
}
and remove the Thread.interrupted() test.
Read the Javadoc on Thread.sleep():
Throws:
...
InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
As soon as the exception is thrown, it's no longer interrupted. In your case, you can immediately break out of the loop and let the thread die, as #EJP suggested. But if your code doesn't have ownership of the thread (e.g. a separate method), you'll want to make sure the interruption is propagated to the caller, either by propagating the exception, or by re-interrupting:
try {
while (true) {
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
Thread.sleep(5000L);
}
} catch (InterruptedException notIgnored)
Thread.currentThread().interrupt();
}
Or similarly:
while (!Thread.currentThread().isInterrupted()) {
System.out.printf("[%d]:%d\n", Thread.currentThread().getId(), ++count);
try {
Thread.sleep(5000L);
} catch (InterruptedException notIgnored)
Thread.currentThread().interrupt();
}
}

Single Thread.interrupt() interrupts more than once

I created MyTask which has 3 things to do inside run(). I try to interrupt() the thread which holds MyTask instance. Unfortunately once it is interrupted, it ends and only string First task is printed on the console.
public class MyTask implements Runnable {
private volatile Thread thread;
#Override
public void run() {
while (!thread.isInterrupted()) {
System.out.println("First task");
}
while (!thread.isInterrupted()) {
System.out.println("Second task");
}
while (!thread.isInterrupted()) {
System.out.println("Third task");
}
}
public Thread start(){
thread = new Thread(this);
thread.start();
return thread;
}
public static void main(String[] args) throws InterruptedException {
Thread t = new MyTask().start();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
t.interrupt();
}
}
If I add Thread.sleep(10) in the run() it starts to work correctly and it prints First task, Second task and finally Third task on the console.
The question is: Whydoes Thread.interrupts() work correctly only if I add sleep()?
public class MyTask implements Runnable {
private volatile Thread thread;
#Override
public void run() {
while (!thread.isInterrupted()) {
System.out.println("First task");
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
while (!thread.isInterrupted()) {
System.out.println("Second task");
}
try {
Thread.sleep(10);
} catch (Exception e) {
}
while (!thread.isInterrupted()) {
System.out.println("Third task");
}
}
public Thread start(){
thread = new Thread(this);
thread.start();
return thread;
}
public static void main(String[] args) throws InterruptedException {
Thread t = new MyTask().start();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
t.interrupt();
Thread.sleep(1000);
t.interrupt();
}
}
To quote from Interrupts:
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.
Meaning: Change your code from thread.isInterrupted() to Thread.interrupted() and try again.
The sleep() in between your loops will clear that flag as well by throwing InterruptedException immediately (as the current Thread has been interrupted)
Have a look at the Javadoc on Thread.sleep(long)
Throws: InterruptedException - if any thread has interrupted the current thread. The interrupted status of the current thread is cleared when this exception is thrown.
Hence, adding that sleep as well catching (and ingoring) any exception will result in the observed behavior.
Example:
Without the sleep():
Thread starts with interrupted = false thus 1st loop runs
Thread gets interrupted, i.e. now interrupted = true
1st loop checks interrupted and doesn't run (again)
2nd loop checks interrupted and doesn't run at all
3rd loop checks interrupted and doesn't run at all
finished
With the sleep()
thread starts with interrupted = false
loop 1:
while condition is checked and body is executed since interrupted = false
thread gets interrupted, i.e. now interrupted = true
while condition is checked but this time interrupted = true so the loop ends
sleep() is called and since the thread has been interrupted the exception is thrown and interrupted = false again
the exception is caught (and ignored) and thus execution is continued normally
step 2 is repeated for loops 2 and 3
finished

future.cancel does not work

I have a nice and compact code, which does not work as I expected.
public class Test {
public static void main(String[] args) {
Runnable r = new Runnable() {
#Override
public void run() {
try {
for (;;) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
The output is :
Timeout true
END
Question:
Why does not terminate the future.cancel(true) method the called Runnable?
After the program wrote the "END" to the output, the "r" Runnable is still running.
The problem is that your Runnable is not interruptible: task interruption is a collaborative process in Java and the cancelled code needs to check regularly if it's been cancelled, otherwise it won't respond to the interruption.
You can amend you code as follows and it should work as expected:
Runnable r = new Runnable() {
#Override public void run() {
try {
while (!Thread.currentThread().isInterrupted()) {}
} finally {
System.out.println("FINALLY");
}
}
};
This is always a little bit misleading: The ExceutorService or even the underlying thread scheduler do not know anything about what the Runnable is doing. In your case they don't know that there is a unconditional loop.
All these methods (cancel, done, ...) are related to manage Threads in the Executor structure. cancel cancels the thread from the point of view of the Executor service.
The programmer must test if the Runnable was canceled and must terminate the run() method.
So in your case (if I remember well) something like this:
public class Test {
public static void main(String[] args) {
FutureTask r = new FutureTask () {
#Override
public void run() {
try {
for (;!isCancelled();) {
}
} finally {
System.out.println("FINALLY");
}
}
};
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<?> future = executor.submit(r);
try {
future.get(3, TimeUnit.SECONDS);
} catch (TimeoutException e) {
boolean c = future.cancel(true);
System.out.println("Timeout " + c);
} catch (InterruptedException | ExecutionException e) {
System.out.println("interrupted");
}
System.out.println("END");
}
}
When you cancel a Future whose Runnable has already begun, the interrupt method is called on the Thread that is running the Runnable. But that won't necessarily stop the thread. Indeed, if it's stuck in a tight loop, like the one you've got here, the Thread won't stop. In this case, the interrupt method just sets a flag called the "interrupt status", which tells the thread to stop when it can.
See the Javadoc for the interrupt method of Thread
Future.cancel() will cancel any queued task or will call Thread.interrupt() on your thread if already running.
You need to interrupt your code
It's 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.

Method call from thread does not finish - How to end the thread - Workaround

I have a following code.
ReadWriteLock someLock = new ReentrantReadWriteLock();
Condition someCondition = someLock.writeLock().newCondition();
public someMethod() {
// do some stuff
someCondition.await(); //Lock here.
System.out.prinltn("This never prints");
}
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
When the thread calls the method someMethod() it gets executed. But since there is an await() method on that function. It never ends / it does not print 'This never prints', unless its woken up by singnalAll(). But I want the thread to be finished once its executed.
I cannot refactor the whole thing. I just need a workaround to this problem. Its used in Swing application. So thread is important.
I think, this will do:
Thread thread =
new Thread(new Runnable() {
#Override
public void run() {
try {
someMethod();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
});
thread.start( );
final long reasonableTimeout = ...;
thread.join( reasonableTimeout );
// THIS WILL SHAKE IT UP
thread.interrupt( );
thread.join( );
// At this point, it is guaranteed that the thread has finished
I am not sure if I understood your question correctly but I think you want to start the someMethod() function and then make the caller exit without waiting for someMethod() to finish. This means you are basically branching your execution flow into two, one where the someMethod() running waiting for its due awakening and the other where the caller just continues on(which it will need to do if you want it to finish) after calling someMethod(). To do this you will have to run someMethod() in a separate thread. Something like this.
public doSomeStuff() {
new Thread(new Runnable() {
#Override
public void run() {
try {
new Thread(){
public void run(){
someMethod();
}
}.start();
System.out.println("thread finished");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("thread is going to die");
}
}).start();
}
Two ways you can sort this out.
1) Design your task with Interruption Policy
Do a defensive coding. If your task is interrupted by any means, the program should know how to deal with that.
2) Add a POISON PILL as in this example, Once you
public someMethod() {
while(condition predicate){
someCondition.await(TIME_OUT); //Lock here.
}
//ADD Poison pill here
System.out.prinltn("This never prints");
}
As Per Java Concurrency in Practice
When using condition waits (Object.wait or Condition.await):
1)Always have a condition predicate some test of object state that must hold before
proceeding;
2)Always test the condition predicate before calling wait, and again after returning from
wait;
3)Always call wait in a loop;
4)Ensure that the state variables making up the condition predicate are guarded by the lock
associated with the condition queue;
5) Hold the lock associated with the the condition queue when calling wait, notify, or
notifyAll; and
6)Do not release the lock after checking the condition predicate but before acting on it.

Categories

Resources