I have a program with multiple threads operating on a single instance of a class. Sometimes one of these threads will get interrupted. I have in the method header "throws InterruptedException" so it does that part correctly. The problem is that when a thread gets interrupted, the fields don't get reset, so the next thread that comes in gets all messed up.
How do I check if a thread is interrupted so that I can reset the variables for the next thread that comes in? I'm not sure where to address this in my code. I have tried something like:
if(Thread.currentThread().isInterrupted()) {
//reset variables here
}
or:
if(Thread.interrupted()) {
//reset variables here
}
Can anyone help me out? Thank you in advance!
You can encase your whole thing in a try-catch block:
try {
//Code here
} catch (InterruptedException e) {
//Reset variables here
}
You can check (or handle) if a thread has been interrupted in two ways:
You receive an InterruptedException when performing operations that might keep your thread waiting for an undefined amount of time, like a sleep or a wait invocation.
public class MyRunnable implements Runnable {
public void run(){
try {
while(true){
someOperation();
TimeUnit.SECONDS.sleep(2);
}
} catch(InterruptedException ex) {
//reset variables
}
}
}
If you're performing some heavy operations, you might wanna check in specific points of your code if you've received an interruption with the methods you mentioned above.
public class MyRunnable implements Runnable {
public void run(){
while(true){
someHeavyOperation();
if (Thread.currentThread().isInterrupted()){
//reset variables
return;
}
}
}
}
Here's also a link to the Oracle Tutorials explaining Java's support to thread interruption
https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
Related
I've seen a lot of example for wait and notify, but still I have a problem.
public class Main(){
public static void main(String args[]) throws Exception {
MyThread s = new MyThread();
s.start();
}
}
class MyThread extends Thread {
public void run() {
k();
}
public synchronized void k() {
System.out.println("before wait");
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("do something after wait");
}
public synchronized void m() {
for (int i=0;i<6;i++)
System.out.println(i);
notify();
}
}
The only output I get when run the program is: "before wait".
The thread you create in main invokes MyThread#k() which goes into a wait. At that point, that thread will do nothing else until it is awakened or interrupted. But the only place in your code where it could possibly be awakened is the notify in MyThread#m(). Since nothing in your program calls that method, the thread can never be awoken.
What you probably want is to add a call to s.m() right after s.start() in your main program. That way your main thread will execute the notify that's needed to wake up your thread.
Unfortunately, that's very unlikely to work. The problem is that s.start() causes your created thread to become ready to run, but it doesn't necessarily run immediately. It could well happen that your call to s.m() will complete before the created thread does anything. And then you'll still have exactly the same result as before, except that you'll see the integers 0..6 printed out before before wait. The notify will do nothing, because the child thread has not yet performed its wait. (And by the way, since both MyThread#k() and MyThread#m() are both synchronized, increasing your loop limit in MyThread#m() won't change a thing... the child thread won't be able to enter MyThread#k() while MyThread#m() is running. You could improve that by putting the notify in a sycnchronized block rather than making all of MyThread#m() synchronized.)
You can try to get around this by adding Thread.sleep(1000) before s.m() in your main program. That will almost certainly work because your main thread will yield execution, giving your JVM the opportunity to schedule the child thread for some useful work. By the time the main thread wakes out of its sleep and performs its s.m() call, the child will probably have executed its wait and you will then see your do something after wait message.
But that's still pretty crummy, because it still depends on scheduling events that you don't really have any control over. There's still no guarantee that the wait will happen before the notify.
This is why when using wait/notify you should generally arrange for there to be some sort of reliable test as to whether whatever you're waiting to be done has actually occurred. This should be a condition that, once it turns turns true, will remain true at least until the test has been subsequently performed. Then your typical wait loop looks something like this:
while (!isDone()) {
synchronized(monitorObject) {
try {
monitorObject.wait();
} catch (InterruptedException e) {
}
}
}
Putting the whole thing in a loop takes care of premature waking, e.g. due to InterruptedException.
If the required work has already occurred by the time this code is executed, no wait occurs, and the notify executed by the code that did the work was a no-op. Otherwise, this code waits, and the code completing the work will eventually do a notify which will wake this code up as required. Of course, it's critical that, at the time the notify is performed, the wait condition (isDone() above) be true and remain true at least until tested.
Here's a corrected version of your code that incorporates a proper wait loop. If you comment out the Thread.sleep() call, you will likely not see the waiting message, because the work will complete before the wait loop even starts. With the sleep included, you'll probably see the waiting message. But either way, the program will work properly.
public static void main(String[] argv) throws Exception {
MyThread s = new MyThread();
s.start();
Thread.sleep(1000);
s.m();
}
class MyThread extends Thread {
#Override
public void run() {
k();
}
private boolean done = false;
public void k() {
System.out.println("before wait");
while (!done) {
System.out.println("waiting");
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
}
}
}
System.out.println("do something after wait");
}
public void m() {
for (int i = 0; i < 6; i++) {
System.out.println(i);
}
synchronized (this) {
done = true;
notify();
}
}
}
The problem is, that you're not calling your m method, so notify is never called, so your thread sleeps forever. You could call it in main, after the start, using s.m():
MyThread s = new MyThread();
s.start();
s.m();
Maybe you should sleep for a little time before calling the m method, as it could run sooner than k in the thread:
s.start();
try {
Thread.sleep(200);
} catch (InterruptedException e) {
// nothing to do
}
s.m();
Not closely related to the question, but a throws declaration in main is not very advisable, even a generated printStackTrace is better than throwing the exception away.
I faced an issue of creating stop/start jbuttons for my gui, and after a LOT of googling, i realized i needed multi-threading. Upon further reading i discovered the swingworker class, and i managed to get my GUI to respond to the STOP button.
now my problem is this
The doinbackground() method executes a piece of code that captures packets in an infinite while loop with the condition (!isCancelled), and once it is cancelled (The STOP button executes worker.cancel()) it returns an ArrayList of packets which theoretically, i should be able to obtain inside the done() method using get(). right? But when i try to do this i get a CancellationException and this is driving me nuts right now.
any help would be highly appreaciated!
Thank you
edit: obj is an ArrayList declared outside of the class to store the return values.
here is my code executed by the START jbutton
private void jButton5ActionPerformed(java.awt.event.ActionEvent evt) {
final ArrayList packet_list = new ArrayList();
obj.clear();
try {
worker = new SwingWorker<ArrayList,Integer>(){//initialze swingworker class
#Override
protected void done(){
try {
obj = get();
}
catch (InterruptedException ex) {
Logger.getLogger(NewJFrame3.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(NewJFrame3.class.getName()).log(Level.SEVERE, null, ex);
}
}
//opens up stuff required to capture the packets
NetworkInterface [] devices = JpcapCaptor.getDeviceList();
int index = (jComboBox5.getSelectedIndex()-1);
JpcapCaptor captor =JpcapCaptor.openDevice(devices[4], 65535, false, 20);
#Override
protected ArrayList doInBackground(){
while(!isCancelled()){
try {
Packet packets = captor.getPacket(); //captures packets
if (packets != null) //filters out null packets
{
//System.out.println(packets);
packet_list.add(packets); //adds each packet to ArrayList
}
Thread.sleep(100);
} catch (InterruptedException ex) {
return packet_list;
}
}
return packet_list;
}
};
worker.execute();
} catch (IOException ex) {
Logger.getLogger(NewJFrame3.class.getName()).log(Level.SEVERE, null, ex);
}
}
The stop button simply executes
worker.cancel(); no errors there. and this is the swingworker declaration
private SwingWorker<ArrayList,Integer> worker;
cancel doesn't just set the isCancelled flag for you to read at your leisure. That would be pretty much useless. It prevents the task from starting if it hasn't already and may actively interrupt the thread if it's already running. As such, getting a CancellationException is the natural consequence of cancelling a running task.
To further the point, the Javadoc on isCancelled states:
Returns true if this task was cancelled before it completed normally.
Hence if this returns true, then your task cannot complete normally. You cannot cancel a task and expect it to continue as per normal.
SwingWorker docs say "An abstract class to perform lengthy GUI-interaction tasks in a background thread". However, the definition of "lengthly" is different for GUI and for an application lifetime. A 100ms task is very long for a GUI, and is best done by a SwingWorker. A 10 minute task is too long for a SwingWorker simply because it has a limited thread pool, that you may exhaust. Judging by your problem description, you have exactly that - a potentially very long running task. As such, you should rather make a proper background thread than use a SwingWorker.
In that thread, you would have either an AtomicBoolean or simply a volatile boolean flag that you can manually set from the EDT. The thread can then post an event to the EDT with the result.
Code:
class PacketCaptureWorker implements Runnable {
private volatile boolean cancelled = false;
public void cancel() {
cancelled = true;
}
public void run() {
while (!cancelled) {
//do work
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
//Use the result of your computation on the EDT
}
});
}
}
new Thread(new PacketCaptureWorker()).start();
I tried using a volatile boolean instead of using worker.cancel() for the swingworker thread while loop and it works beautifully. (atleast on surface) I managed to create a normal background thread as well and that too worked liked a charm :D Many thanks you saved me a major headache! Wondering what the best method is out of the two.
A follow up, i had to make the volatile boolean available for the whole class, because i had to create 2 seperate instances for the thread class, one to use the START and the other to use the STOP. Apparently two different instances does not address the same instance of the variable. is this bad practice?
I want to resume the work of interrupted thread,please let me know some possible solutions for the same.
class RunnableDemo implements Runnable
{
public void run()
{
while(thread.isInterrupted())
{
try{}
catch(Exception e){ //exception caught}
}
}
}
If exception is caught, thread is interrupted, but even though exception is caught, i want thread to continue its work, so please suggest me some way to overcome this issue.
Thanks in advance
Thread interruption is something you choose to obey when writing a thread. So if you don't want your thread to be interrupted, don't check the interrupted status and continue regardless.
The only time you'll need try/catch statements (with respect to thread interruption) is when calling blocking methods that throw InterruptedException. Then you'll need to avoid letting that exception stop your thread's work.
Of course... you should give some thought about whether this is a suitable way to behave. Thread interruption is a helpful thing and choosing not to adhere to it can be annoying to users of your code.
I have written a reusable code for getting this feature where thread can be pause and resume. Please find the code below. Your can extend PausableTask and override task() method:
public abstract class PausableTask implements Runnable{
private ExecutorService executor = Executors.newSingleThreadExecutor();
private Future<?> publisher;
protected volatile int counter;
private void someJob() {
System.out.println("Job Done :- " + counter);
}
abstract void task();
#Override
public void run() {
while(!Thread.currentThread().interrupted()){
task();
}
}
public void start(){
publisher = executor.submit(this);
}
public void pause() {
publisher.cancel(true);
}
public void resume() {
start();
}
public void stop() {
executor.shutdownNow();
}
}
Hope this helps. For further details check this link or give me shout in comment section.
http://handling-thread.blogspot.co.uk/2012/05/pause-and-resume-thread.html
A thread get's interrupted only if someone called the interrupt() method of that thread and not because some other random exception was thrown while running your thread as you are thinking.
When the thread's interrupted() method is called, InterruptedException will be thrown in the thread if the thread is in the middle of a blocking operation (eg. IO read).
When the InterruptedException is thrown you should know that the interrupted status is cleared, so the next time you call isInterrupted() in your thread will give you false (even though you just cauth the InterruptedException)
Have this in mind while coding your threads. And if you don't understand what I am talking about stop coding multithreading and go read some books about concurrency in java.
One caveat: If your thread handles an InterruptedException while in a call to a third-party library, then you won't necessarily know how the library reacted to it (i.e., did it leave the library objects in a state when it makes sense for your program to continue using them?)
Some developers (including some library developers) mistakenly assume that an interrupt means, "shut down the program," and all they worry about is closing files, etc.; and not so much about whether the library can continue to be used.
Try it and see, but if you're writing code to control a spacecraft or a nuclear reactor or something, then you may want to do a little extra work to really find out what the library does.
As others already stated, usually interruption is the proper way to cancel a task. If you really need to implement a non-cancellable task, at least make sure to restore the interrupted-state of the thread when you're done with your non-interruptible work:
public void run() {
boolean interrupted = false;
try {
while (true) {
try {
callInterruptibleMethod();
} catch (InterruptedException ex) {
interrupted = true;
// fall through and retry
}
}
} finally {
if (interrupted) {
// restore interruption state
Thread.currentThread().interrupt();
}
}
}
(From book: Java Concurrency in Practice)
I am starting two thread one after the other.
The first thread is reading in a loop from input and the other one check some condition in a loop to
sent an interrupt to the other.
The problem is that any thread of the two I start first it doesnt let the other stop.
If i start reading in never runs the other thread until it finishes and if I start the other thread is checking the condition in the loop and it wont move forward in code until the condition is true and gets out of the loop.
What is the correct way to do it?
Sample code below:
Thread 1)
public class InterruptionThread extends Thread {
public void run() {
while (condition not true) {
try {
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
if (condition true) {
do some work
return;
}
}
}
Thread 2)
public class ReadingThread extends Thread{
public void run() {
int input;
while (true) {
try {
input = stdInput.read();
} catch (IOException e) {
e.printStackTrace();
return;
}
System.out.print((char) input);
}
}
}
This sounds like you are not starting the threads in a correct manner.
Use the start() method to start threads, not the run() method (which doesn't actually start a thread).
new InterruptionThread().start();
new ReadingThread().start();
I think your problem is of producer consumer problem type.
So would suggest you to use BlockingQueue.
http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html
Also instead of directly handling threads; it will be easy if you use Executor Framework; this way thread management will become pretty easy.
I have a short version of the question:
I start a thread like that: counter.start();, where counter is a thread.
At the point when I want to stop the thread I do that: counter.interrupt()
In my thread I periodically do this check: Thread.interrupted(). If it gives true I return from the thread and, as a consequence, it stops.
And here are some details, if needed:
If you need more details, they are here. From the invent dispatch thread I start a counter thread in this way:
public static void start() {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
showGUI();
counter.start();
}
});
}
where the thread is defined like that:
public static Thread counter = new Thread() {
public void run() {
for (int i=4; i>0; i=i-1) {
updateGUI(i,label);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
// The time for the partner selection is over.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.remove(partnerSelectionPanel);
frame.add(selectionFinishedPanel);
frame.invalidate();
frame.validate();
}
});
}
};
The thread performs countdown in the "first" window (it shows home much time left). If time limit is over, the thread close the "first" window and generate a new one. I want to modify my thread in the following way:
public static Thread counter = new Thread() {
public void run() {
for (int i=4; i>0; i=i-1) {
if (!Thread.interrupted()) {
updateGUI(i,label);
} else {
return;
}
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
// The time for the partner selection is over.
if (!Thread.interrupted()) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.remove(partnerSelectionPanel);
frame.add(selectionFinishedPanel);
frame.invalidate();
frame.validate();
}
});
} else {
return;
}
}
};
ADDED:
Because of some reasons it does not work. I have a method which interrupts the thread:
public static void partnerSelected() {
System.out.println("The button is pressed!!!!");
counter.interrupt();
}
This method is activated when a button is pressed. When I press the button I see the corresponding output in the terminal (so this method is activated and it does something). But because of some reasons it does not interrupt the thread. Here is the code for the thread:
public static Thread counter = new Thread() {
public void run() {
for (int i=40; i>0; i=i-1) {
if (Thread.interrupted()) {
System.out.println("Helloo!!!!!!!!!!!!!!!");
return;
}
updateGUI(i,label);
try {Thread.sleep(1000);} catch(InterruptedException e) {};
}
// The time for the partner selection is over.
if (Thread.interrupted()) {
System.out.println("Helloo!!!!!!!!!!!!!!!");
return;
}
SwingUtilities.invokeLater(new Runnable() {
public void run() {
frame.remove(partnerSelectionPanel);
frame.add(selectionFinishedPanel);
frame.invalidate();
frame.validate();
}
});
}
};
P.S. I do not see "Hello!!!!!!!!!!!!!" in the terminal...
Pretty close to the right idea. However, in your catch (InterruptedException) you should have:
Thread.currentThread().interrupt();
so that the interrupted status goes on again, and doesn't do the stuff in the second block.
Edit to make my point clearer (because the OP's edit seems to have missed my initial point :-P): you should write your code like this:
try {
for (int = 40; i > 0; --i) {
updateGUI(i, label);
Thread.sleep(1000);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt(); // <-- THIS LINE IS IMPORTANT
}
Second edit to explain what interruption does. :-)
When you call thread.interrupt(), that thread's interrupted flag is set. That flag doesn't do anything on its own; it's just a variable. The reason for this is because interruption supports something called "cooperative thread management", where the thread's running code decides what to do when interrupted (rather than being forced to quit on the spot).
Some functions built into the JDK, like Thread.sleep, or Object.wait, or Lock.lockInterruptibly, will check the flag, and if it's set, then it'll throw an InterruptedException after clearing the flag.
So, if you're calling one of those functions, you don't need to manually check the interrupted flag. But if you're not, e.g., if you're doing intensive processing instead of waiting for something, then you should periodically check the flag.
There are two ways to check the flag:
interrupted()
isInterrupted()
The first one clears the interrupted flag; the second one doesn't. You have to decide which version is "more correct" for your application logic.
Yes it is the way to go
It's considered a better way (link) to use separate volatile variable (boolean isStopped) for this purpose.
Assume that interrupted() method changes value from true to false if your thread was interrupted, i.e.:
System.out.println (Thread.interrupted()); //true
System.out.println (Thread.interrupted()); //false
The alternative is isInterrupted() method.
Check out this article from the JavaSpecialists newsletter, which covers how to interrupt() threads and manage this properly.
Edit/Preamble
I'd like to edit and note that I've learned a lesson here today. There's no reason to implement a boolean as I explain in the following two paragraphs; the interrupt mechanism does that for me. For some reason I had assumed that "interrupt" stops the thread dead in its tracks (I don't know what I thought isInterrupted() did then!).
So, here is an example of what not to do. Keep on using your interrupt technique!
Original answer
I tend to avoid interrupt, but especially to stop a thread. In your case, you're trying to use interrupt() as an alternative to stop(), which has been deprecated for good reason. All you need to do is declare a boolean which represents whether the thread should stop counting, and have the thread continuously check that boolean value. Then, when the parent thread is ready for the counter to stop, it should set the boolean to true (stop), which will cause the counter thread to stop as soon as it checks the value again.
In your Counter thread's anonymous class definition, add public volatile boolean shouldStop;. At the beginning of run(), set shouldStop = false;. Then replace all Thread.interrupted() with shouldStop (in your if statements). Finally, instead of calling counter.interrupt(), just say counter.shouldStop = true;. You can additionally call counter.join() right after setting shouldStop=true if you want to ensure that counter has stopped before continuing.