Java: How to continue execution after thread is started? - java

I'm starting a thread which loops indefinitely until a certain event occurs. The problem is, I want to start this thread, and then return to the normal execution of my program. However, after starting the thread, the code seems to get stuck.
Code:
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).run();
System.out.println("Returning");
return;
}
When I start this, I get the output "Starting thread" but I don't get "returning" until the conditions for the while loop in the run() stop being true.
Any ideas how I can make it work asynchronously?

Use start rather than run to start a Thread. The latter just invokes the run method synchronously
new Thread(thread).start();
Read: Defining and Starting a Thread

You may try this in your code:-
new Thread(thread).start();
like:-
public void init()
{
Runnable thread = new Runnable()
{
public void run()
{
while(something)
{
//do something
}
}
};
System.out.println("Starting thread..");
new Thread(thread).start(); //use start() instead of run()
System.out.println("Returning");
return;
}

You want to call new Thread(thread).start() instead of run().

Are you sure about your approach? You say:
The thread should loop indefinitely until certain event occurs.
that's an enormous loss of computational resource, the program is principally bound to get slow & fail. You may want to put the thread in wait() mode and catch InterruptedException to wake it up upon occurrence of your event of interest. If this preliminary understanding of what you are trying to accomplish is true then Id' strongly suggest you to revise your approach. Computing resource is expensive, don't waste it in relentless looping.

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.

Proper way to end an instance of a class?

In my Android app, I have a class that extends Thread that runs when there's an established internet connection (3G/WIFI).
When the app is loaded, if an internet connection is established, I instantiate the class like this:
MyThread thread = new MyThread(); // (it calls its own start() method)
In the thread, if the connection is lost, I want to destroy the Thread. I was told not to run finalize(), how would I destroy it so that thread == null is true?
Edit: The reason I was asking was, later on, I would like to restart the thread in case connectivity returned, and a check to see if (thread == null) would have been easy. I could just use a flag to indicate the thread needs to be restarted or check to see if it was interrupted. Thanks for the helpful comments so far.
Generally, you don't subclass Thread. You create a Runnable, and pass it into a Thread object, or better yet, an ExecutorService.
But you don't have to worry about cleaning up after the thread is done, it will be handled automatically by the garbage collector. If you want your own local reference to be null, just null it out yourself, or better yet, don't hang on to it.
new Thread( new Runnable() {
public void run() {
// put your stuff here
}
} ).start();
Try this,
A thread of execution will live until it has finished executing its run() method, then
it either moves to the dead state or in the thread pool.
Its always better to control the run() method using aboolean variable.
eg:
boolean isRunning = true;
new Thread(new Runnable()
{
public void run()
{
while(isRunning)
{
// Keep doing your work here....
if (!isRunning){
break;
}
}
}
}).start();

How to stop a java thread gracefully?

I wrote a thread, it is taking too much time to execute and it seems it is not completely done. I want to stop the thread gracefully. Any help ?
The good way to do it is to have the run() of the Thread guarded by a boolean variable and set it to true from the outside when you want to stop it, something like:
class MyThread extends Thread
{
volatile boolean finished = false;
public void stopMe()
{
finished = true;
}
public void run()
{
while (!finished)
{
//do dirty work
}
}
}
Once upon a time a stop() method existed but as the documentation states
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.
That's why you should have a guard..
The bad part about using a flag to stop your thread is that if the thread is waiting or sleeping then you have to wait for it to finish waiting/sleeping. If you call the interrupt method on the thread then that will cause the wait or sleep call to be exited with an InterruptedException.
(A second bad part about the flag approach is that most nontrivial code is going to be utilizing libraries like java.util.concurrent, where the classes are specifically designed to use interruption to cancel. Trying to use the hand rolled flag in a task passed into an Executor is going to be awkward.)
Calling interrupt() also sets an interrupted property that you can use as a flag to check whether to quit (in the event that the thread is not waiting or sleeping).
You can write the thread's run method so that the InterruptedException is caught outside whatever looping logic the thread is doing, or you can catch the exception within the loop and close to the call throwing the exception, setting the interrupt flag inside the catch block for the InterruptedException so that the thread doesn't lose track of the fact that it was interrupted. The interrupted thread can still keep control and finish processing on its own terms.
Say I want to write a worker thread that does work in increments, where there's a sleep in the middle for some reason, and I don't want quitting the sleep to make processing quit without doing the remaining work for that increment, I only want it to quit if it is in-between increments:
class MyThread extends Thread
{
public void run()
{
while (!Thread.currentThread().isInterrupted())
{
doFirstPartOfIncrement();
try {
Thread.sleep(10000L);
} catch (InterruptedException e) {
// restore interrupt flag
Thread.currentThread().interrupt();
}
doSecondPartOfIncrement();
}
}
}
Here is an answer to a similar question, including example code.
You should not kill Thread from other one. It's considered as fairly bad habit. However, there are many ways. You can use return statement from thread's run method.
Or you can check if thread has already been interrupted and then it will cancel it's work. F.e. :
while (!isInterrupted()) {
// doStuff
}
Make a volatile boolean stop somewhere. Then in the code that runs in the thread, regularly do
if (stop) // end gracefully by breaking out of loop or whatever
To stop the thread, set stop to true.
I think you must do it manually this way. After all, only the code running in the thread has any idea what is and isn't graceful.
You need to send a stop-message to the Thread and the Thread itself needs to take action if the message has been received. This is pretty easy, if the long-running action is inside loop:
public class StoppableThread extends Thread {
private volatile boolean stop = false;
public void stopGracefully() {
stop = true;
}
public void run() {
boolean finished = false;
while (!stop && !finished) {
// long running action - finished will be true once work is done
}
}
}
For a thread to stop itself, no one seems to have mentioned (mis)using exception:
abstract class SelfStoppingThread extends Thread {
#Override
public final void run() {
try {
doRun();
} catch (final Stop stop) {
//optional logging
}
}
abstract void doRun();
protected final void stopSelf() {
throw new Stop();
}
private static final class Stop extends RuntimeException {};
}
A subclass just need to override doRun() normally as you would with a Thread, and call stopSelf() whenever it feels like it wants to stop. IMO it feels cleaner than using a flag in a while loop.

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