I have a Java 8 application where I run a task on a thread:
Thread t = new Thread(() -> { runTask();
finalizeTask(); });
t.start()
saveThread(t);
At some point, from a different thread, this task may be interrupted:
Thread t = getThread(); // Obtains thread t
t.interrupt();
With this, I want the runTask(); line to be interrupted, but I'd still like the finalizeTask(); to run.
How can I catch the thread interruption and deal with it?
You can use try catch finally for this.
try {
runTask();
}
catch (InterruptedException e) {
// Log etc.
}
finally {
finalizeTask();
}
This will ensure that that finalizeTask always executes.
Related
I have a question about threads in Java.
I have the following code:
public static void main(String[] args) {
Runnable r = () -> {
while (!Thread.interrupted()) {
System.out.println("Hola");
try {
Thread.sleep(100);
} catch (InterruptedException e) {
System.out.println("interrupted");
break;
}
}
};
Thread t = new Thread(r);
t.start();
try {
Thread.sleep(2000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
t.interrupt();
}
Why if I introduce an interrupt does it still enter the loop? (without break).
I understand the operation of the thread when there is an exception.
Whenever the sleep method detects an interruption it resets the interrupt flag before throwing an InterruptedException. So if you don't use break then the interrupt flag is set to false by the time the exception is caught and the while loop test never detects the interruption.
The recommended practice is to add a line to your catch block like this
Thread.currentThread.interrupt();
if you want to keep the interrupt status.
It's not a problem here but be aware that Thread.interrupted() resets the interrupt flag. It's a convenience method used by some JDK code so that resetting the interrupt flag and throwing the exception takes less code.
Problem
I am using a completion service and spawning child threads to perform some ETL.
As I debug in my IDE and then stop all processes, I notice I still have a bunch of zombie threads killing my CPU. This is due to the fact that I'm not terminating the child threads properly.
Minimum Example
Future<Boolean> future = completionService.submit(conversionProcessor);
boolean isCompleted = false;
while (!isCompleted && !closed.get()) {
try {
isCompleted = future.get(CONSUMER_HEARTBEAT_INTERVAL,
TimeUnit.SECONDS); // Wait until heartbeat interval exceeds
if (isCompleted) {
// do some things here
future.cancel(true);
break;
}
} catch (TimeoutException e) {
// Used to keep consumer alive in the cluster
consumer.poll(Duration.ofSeconds(CONSUMER_HEARTBEAT_INTERVAL)); // does heart-beat
} catch (CancellationException e) {
future.cancel(true);
break;
} catch (InterruptedException e) {
future.cancel(true);
break;
} catch (WakeupException we) {
future.cancel(true);
break;
} catch (Exception e) {
future.cancel(true);
break;
}
Thoughts
Essentially, I submit my Callable<Boolean> to my completion service.
ExecutorCompletionService<Boolean> completionService = new ExecutorCompletionService<>(
Executors.newSingleThreadExecutor());
If I stop the debugger, this thread is presumably still running. I just added this future.cancel(true) piece, which seems to have stopped continuously uploaded files from my child thread, but I still see these java processes running on my activity monitor.
I'm wondering how I should be thinking about this? I want the callable as it tells me when the underlying ETL has completed or not (true/false)
edit:
future.cancel actually seems to be helping quite a bit.. Is this what I want to be using?
Once you are done with your CompletionService you need to shutdown underlying executor so you need to do the following
ExecutorService es = Executors.newSingleThreadExecutor();
ExecutorCompletionService<Boolean> completionService = new ExecutorCompletionService<>(es);
And a the end call
es.shutdown();
es.awaitTermination(1, TimeUnit.SECONDS);
This question already has answers here:
Thread.interrupt () doesn't work
(2 answers)
Closed 6 years ago.
onIncomingCall() is a overridden method from a class in third party library pjsip. This method is called when an incoming call is made using SIP. Somehow this method makes it possible for the call to be answered ONLY if the Call answering code be inside the same method or called within the same method. But I want the call to be answered when the user presses the button. I have created a call back and make the user press the button when the call comes but the call answering code is not working if its called outside of onIncomingCall() method. So I decided to put Thread.sleep(10000) in onIncomingCall() and when the user presses the button I would like to cancel this thread so that the call answering code can be executed.
I used Thread.currentThread().interrupt() but the Thread.sleep is not cancelled at all. I wrote a separate activity to test this functionality but it failed, meaning Thread.currentThread.interrupt is not working in for me at all. What is the best option to achieve this? Kindly please update me .. I am really struggling with this.
#Override
public void onIncomingCall(OnIncomingCallParam prm) {
onIncomingCallParam = prm;
try {
Thread.sleep(10000);
} catch(InterruptedException ie) {
ie.printStackTrace();
}
answerCall();
}
UPDATE:
I fixed the issue with the below approach
resetThread();
while (testThread) {
try {
Log.d(TAG,"testThread true");
Thread.sleep(1000);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
Log.d(TAG,"Call Answering code");
private void resetThread() {
Thread newThread = new Thread(new Runnable() {
#Override
public void run() {
try {
Thread.sleep(10000);
testThread = false;
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
});
try {
newThread.start();
} catch (Exception ie) {
ie.printStackTrace();
}
}
The problem here is related to the fact that you don't interrupt the right Thread, if you call Thread.currentThread().interrupt(), you will interrupt the current thread not the one that it is currently sleeping.
Here is a clear example to show the main idea:
// Here is the thread that will only sleep until it will be interrupted
Thread t1 = new Thread(
() -> {
try {
Thread.sleep(10_000L);
System.err.println("The Thread has not been interrupted");
} catch (InterruptedException e) {
System.out.println("The Thread has been interrupted");
}
}
);
// Start the thread
t1.start();
// Make the current thread sleep for 1 sec
Thread.sleep(1_000L);
// Try to interrupt the sleeping thread with Thread.currentThread().interrupt()
System.out.println("Trying to call Thread.currentThread().interrupt()");
Thread.currentThread().interrupt();
// Reset the flag to be able to make the current thread sleep again
Thread.interrupted();
// Make the current thread sleep for 1 sec
Thread.sleep(1_000L);
// Try to interrupt the sleeping thread with t1.interrupt()
System.out.println("Trying to call t1.interrupt()");
t1.interrupt();
Output:
Trying to call Thread.currentThread().interrupt()
Trying to call t1.interrupt()
The Thread has been interrupted
As you can see in the output, the thread is interrupted only when we call t1.interrupt(), in other words only when we interrupt the right Thread.
Maybe all calls has to be done on the same thread, which created library instance. Try using HandlerThread for posting it messages and handle those messages inside custom Handler instead of suspending thread.
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.
I'm currently attempting to write a Logger style thread. I'm not using the existing API because this is partially an exercise to improve my threading.
When the thread is interrupted, I need it to shutdown gracefully, flushing the last of it's queued messages and closing the file streams.
Currently, it shuts down but messages are often still in queue, and I'm concerned that the file streams aren't being closed gracefully.
This is my run()
while(!shutdown){
writeMessages();
try{
Thread.sleep(5000);
}
catch (InterruptedException e) {
}
}try {
writeMessages();
} catch (CustomException e1) {
e1.printStackTrace();
}
try {
logFile.close();
} catch (IOException e) {
e.printStackTrace();
}
try {
errFile.close();
} catch (IOException e) {
e.printStackTrace();
}
Java has very neat way to shutdown threads. It's called interruption flag. When you want to interrupt thread you simply write following code:
thread.interrupt();
thread.join();
And in the Runnable of background thread you should check interruption flag and behave accordingly. If you want thread to survive until messages are left you can do it in a following manner (I assume you have some way of checking is there any messages left. In my case it's a BlockingQueue):
Thread self = Thread.currentThread();
BlockingQueue<String> messages = ...;
while (!self.isInterrupted() || !messages.isEmpty()) {
try {
String message = messages.take();
writeMessage(message);
} catch (InterruptedException) {
self.interrupt();
}
}
One more thing. You should ensure that messages are not added to the queue after thread shutdown is requested or shutdown all threads generating messages before writing thread. This also could be done checking thread interruption flag (you need to know reference to a writer thread):
public void addMessage(String message) {
if (thread.isInterrupted() || !thread.isAlive()) {
throw new IllegalStateException();
}
messages.add(message);
}
Also I recommends you to see at java.util.concurrent package. It have a lot of useful tools for multithreaded applications.
Use the finally block to add your flushing instructions.
All other comments are good, I just want to add - make sure that you called flush() on your output streams before closing them.