Terminate Java Thread on Key - java

I am writing a java swing program that involves using a thread to update the UI,
The run function in the thread contains a while loop and a sleep timer,
I want to either terminate the while loop or the thread itself when the user presses for example ctrl+c. The thread includes a sleep command, I don't want the user to have to hold down ctrl+c to terminate, I just want to be able to use those keys once.
How is this possible?
public static void main(String[] args) {
.......//Code to set up window
Thread thread = new Thread(){
#Override
public void run() {
while(user has not terminated the program with ctrl+c){
//Do Something
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
}
}
};
.......//Code to start thread
}

In Java, threads are terminated cooperatively. This means that it requires modifying both the code inside the thread as well as the code outside the thread. Outside the thread, you can signal that the thread should prepare to shutdown by using the Thread.interrupt() method. Inside the thread, you should check Thread.interrupted() to test for interruption (and break from the loop if that is the case). You should also modify your exception handler; the interrupted exception is thrown when Thread.interrupt() was called while the thread was sleeping, so you should modify the content of that handler to break from the loop.

try something like this
class A{
Thread r1Thread;
public static boolean isCtrlCPressed = false;
public static void main(String[] args) {
.......//Code to set up window
MyRun r1 = new MyRun();
r1Thread = new Thread(r1);
r1Thread.start();
}
public void someMethodThatDetectCtrlC(){
r1Thread.interrupt();
}
}
Your Thread
class MyRun implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
try{
Thread.sleep(5000);
}catch(InterruptedException e){
}
}
}

Make a boolean called "running"
Change your while loop to while(running)
Add a keylistener, make it listen for Ctrl + C.
If it hears Ctrl + C, set running = false.
Since running == false, the while loop will then stop.

Related

Stop Thread which doesn't include while statement

All answers are about how to stop loop of some thread, but what if I don't have a loop but I still want to stop a thread before it executes/processes all lines?
For example I have a thread which usually runs for 7-10 seconds and then dies (terminates):
mThread = new Thread(new Runnable() {
#Override
public void run() {
// some code here
// some here
// some here
// some here
// some here
// all lines takes about 7-10 seconds
}
});
If I started a thread and after 2 or 3 seconds I need to stop it, then how to do it and don't wait 10 seconds?
If your thread is not blocked, and is actually processing stuff, then interrupting it might not help. You can code the thread to check for the interrupt flag on the current thread and then stop if it sees that the flag has been set.
This is how you check to see if the current thread has been interrupted.
Thread.currentThread().isInterrupted();
So you would have to code your thread like this...
mThread = new Thread(new Runnable() {
#Override
public void run() {
// some code here
if (Thread.currentThread().isInterrupted()) return;
// some here
if (Thread.currentThread().isInterrupted()) return;
// some here
if (Thread.currentThread().isInterrupted()) return;
// some here
if (Thread.currentThread().isInterrupted()) return;
// some here
// all lines takes about 7-10 seconds
}
});
Then you can go ahead and interrupt the mThread and it will have an effect. Though it will still continue processing the current some here step it is on.
Explanation
The preferred way is to implement a stopping mechanism in the thread. You can also try to observe the interrupt flag. You can interrupt from outside using the Thread#interrupt method and the thread can check the flag using Thread#isInterrupted and Thread#interrupted (see documentation of Thread).
There is no way to force a thread from outside to stop without the thread actually implementing the logic by itself. There is the Thread#stop method but it is deprecated and should never be used. From its documentation:
Deprecated. This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior. Many uses of stop should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?.
Solution
You could modify the thread like this:
public class MyThread implements Runnable {
private volatile boolean mShouldStop = false;
public void shutdown() {
mShouldStop = true;
}
#Override
public void run() {
// First line ...
if (mShouldStop) return;
// Second line ...
if (mShouldStop) return;
// Third line ...
if (mShouldStop) return;
}
}
So you need to periodically check the flag and then manually abort.
Usually such threads have some kind of while (true) loop. In this case it gets easier, you could do:
#Override
public void run() {
while (!mShouldStop) {
// Do something ...
}
}
Depending on your application you might interpret the interruption flag as signal for a thread shutdown. Then your code could look like
#Override
public void run() {
while (!Thread.interrupted()) {
// Do something ...
}
}
Note
The mShouldStop needs to be volatile to ensure it is updated correctly for the Thread. See the tutorial by Oracle for Atomic Access.
You interrupt the thread with mThread.interrupt(). But, for this to work, your thread needs to check the interrupt status (by sleeping). Check out this thread.
For more details, refer this thread.
You need to check the interrupt status in your thread. Something like this
import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;
public class ThreadInterruptor {
private static class Worker implements Runnable {
#Override
public void run() {
while (true) {
IntStream.range(0, Short.MAX_VALUE).forEach(i ->noop());
if (Thread.currentThread().isInterrupted()) {
System.out.println("i got interrupted");
break;
}
}
}
private void noop(){}
}
public static void main(String[] args) throws Exception{
Thread thread = new Thread(new Worker());
thread.start();
TimeUnit.SECONDS.sleep(5);
thread.interrupt();
}
}

Two thread which invokes wait and notify

The code I've witten doesn't work as I expected.
static Integer sync = 1;
static void m() throws Exception {
synchronized (sync) {
System.err.println("First");
sync.notify();
sync.wait(1000L);
System.err.println("Second");
System.err.println("Third");
}
}
public static void main(String[] args) throws Exception {
Runnable r = new Runnable() {
#Override
public void run() {
try {
m();
} catch (Exception ex) {
Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
Runnable t = new Runnable() {
#Override
public void run() {
try {
m();
} catch (Exception ex) {
Logger.getLogger(IO.class.getName()).log(Level.SEVERE, null, ex);
}
}
};
Thread th1 = new Thread(r);
Thread th2 = new Thread(t);
th1.run();
th2.run();
}
We have two threads which execute m()'s syncjronized statement. When the first thread executes one and come across the wait() it'll be added to the wait set. After this, the second thread is starting to execute the synchronized statement, and perform notify(). Since the output must be
First
First
....
But actually it is
First
Second
Third
First
Second
Third
Why?
First of all, your program is not creating any threads. You must call th1.start() and th2.start() to create threads.
t.start() is the method that the library provides for your code to call when you want to start a thread. run() is the method that you provide for the library to call in the new thread. Your run() method defines what the thread will do. IMO, run() was a really misleading name.
Second, notify() and wait() don't do what it looks like you think they will do. In particular, sync.notify() will not do anything at all if there are no other threads currently in sync.wait().
The correct way to use notify() and wait() is, one thread does this:
synchronized(lock) {
while (! someCondition()) {
lock.wait()
}
doSomethingThatRequiresSomeConditionToBeTrue();
}
The other thread does this
synchronized(lock) {
doSomethingThatMakesSomeConditionTrue();
lock.notify();
}
When you use this pattern, no thread should ever change the result of someCondition() except from inside a synchronized(lock) block.
Firstly, To actually create new threads please use
th1.start()
th2.start()
inplace of run() , which is just a regular method call on the thread object.
Secondly, it is possible that the second thread 'th2' did not start running by the time 1000 ms was fninshed , so the first thread finished wait(1000) and executed the remainging lines of code.
if you want the output like so :
first
first
second
third
second
third
then remove the time interval for wait() which will make the threads wait until notified.
as in :
static void m() throws Exception {
synchronized (sync) {
System.err.println("First");
sync.notify();
sync.wait();
System.err.println("Second");
System.err.println("Third");
}
}
Use .start() instead of run() to add runables to the queue instead of running them immediately
Documentation says that wait with timeout waits for any notify on this object or the timeout. In your case when runnables are being executed one by one it goes:
r: First
r: waits 1000ms and try to get lock
r: it already have access to lock object (exactly this code got lock) so continue
r: Second
r: Third
t: First, and so on ...
PS. calling run() and not setting timeout will cause deadlock on t's wait, cause it already has the object but will wait never be notified about it.
Hope this helps.

Endless loop when threading with timer class

I've created a timer class and am testing it with junit4. The timer is notifies another class of the time which then activates a method. While testing I am unable to check what values are sent to the observer because the compiler gets stuck in the always loop used for the timer. Here's the test and the start code for the timer.
public void testSimpleTimerAsThread() throws InterruptedException
{
SimpleTimer st = new SimpleTimer(1000);
st.start();
Thread.sleep(250); // So we are 1/4th a second different
for (int x=0;x<5;x++)
{
assertEquals(x, st.getRound()); // assumes round starts at
Thread.sleep(1000); // wait for the next time change
}
}
public void start()
{
while (flag)
{
timeChanged();
try
{
// Sleep for var seconds.
Thread.sleep(1000);
}
catch (InterruptedException e)
{
}
}
}
Thanks for the help.
In the SimpleTimer class you should be overriding the run() method, not start().
Assuming SimpleTimer extends Thread, you have overridden the method in Thread that actually creates and launches the thread, so no new thread is being created and your thread code is being executed in the main thread when you invoke start(), which is why it hangs.

How to stop a thread created by implementing runnable interface?

I have created class by implementing runnable interface and then created many threads(nearly 10) in some other class of my project.How to stop some of those threads?
The simplest way is to interrupt() it, which will cause Thread.currentThread().isInterrupted() to return true, and may also throw an InterruptedException under certain circumstances where the Thread is waiting, for example Thread.sleep(), otherThread.join(), object.wait() etc.
Inside the run() method you would need catch that exception and/or regularly check the Thread.currentThread().isInterrupted() value and do something (for example, break out).
Note: Although Thread.interrupted() seems the same as isInterrupted(), it has a nasty side effect: Calling interrupted() clears the interrupted flag, whereas calling isInterrupted() does not.
Other non-interrupting methods involve the use of "stop" (volatile) flags that the running Thread monitors.
How to stop a thread created by implementing runnable interface?
There are many ways that you can stop a thread but all of them take specific code to do so. A typical way to stop a thread is to have a volatile boolean shutdown field that the thread checks every so often:
// set this to true to stop the thread
volatile boolean shutdown = false;
...
public void run() {
while (!shutdown) {
// continue processing
}
}
You can also interrupt the thread which causes sleep(), wait(), and some other methods to throw InterruptedException. You also should test for the thread interrupt flag with something like:
public void run() {
while (!Thread.currentThread().isInterrupted()) {
// continue processing
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// good practice
Thread.currentThread().interrupt();
return;
}
}
}
Note that that interrupting a thread with interrupt() will not necessarily cause it to throw an exception immediately. Only if you are in a method that is interruptible will the InterruptedException be thrown.
If you want to add a shutdown() method to your class which implements Runnable, you should define your own class like:
public class MyRunnable implements Runnable {
private volatile boolean shutdown;
public void run() {
while (!shutdown) {
...
}
}
public void shutdown() {
shutdown = true;
}
}
Stopping the thread in midway using Thread.stop() is not a good practice. More appropriate way is to make the thread return programmatically. Let the Runnable object use a shared variable in the run() method. Whenever you want the thread to stop, use that variable as a flag.
EDIT: Sample code
class MyThread implements Runnable{
private volatile Boolean stop = false;
public void run(){
while(!stop){
//some business logic
}
}
public Boolean getStop() {
return stop;
}
public void setStop(Boolean stop) {
this.stop = stop;
}
}
public class TestStop {
public static void main(String[] args){
MyThread myThread = new MyThread();
Thread th = new Thread(myThread);
th.start();
//Some logic goes there to decide whether to
//stop the thread or not.
//This will compell the thread to stop
myThread.setStop(true);
}
}
If you use ThreadPoolExecutor, and you use submit() method, it will give you a Future back. You can call cancel() on the returned Future to stop your Runnable task.
Stopping (Killing) a thread mid-way is not recommended. The API is actually deprecated.
However, you can get more details including workarounds here: How do you kill a Thread in Java?
Thread.currentThread().isInterrupted() is superbly working. but this
code is only pause the timer.
This code is stop and reset the thread timer.
h1 is handler name.
This code is add on inside your button click listener.
w_h =minutes w_m =milli sec i=counter
i=0;
w_h = 0;
w_m = 0;
textView.setText(String.format("%02d", w_h) + ":" + String.format("%02d", w_m));
hl.removeCallbacksAndMessages(null);
Thread.currentThread().isInterrupted();
}
});
}`

Is it a good way to close a thread?

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.

Categories