Reputation: 581
I have developed a code that will start two threads upon executing
public class MyThread1 extends Thread //extend thread class
{
// public synchronized void run()
//synchronized (this)
public void run()
{//synchronized(this)
//{
for(int i=0;i<20;++i) {
try{
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
}catch(Exception e)
{e.printStackTrace();}
//}
}
}
public static void main(String... a)
{
MyThread1 t = new MyThread1();
Thread x = new Thread(t);
Thread y = new Thread(t);
x.start();
y.start();
}
Now it starts both the threads but what if I want to stop a particular thread, lets say I want to stop Thread Y then How I will do it please advise since stopping a thread means that it's run method is completed but I want to stop it forcefully how I will do this, please advise
Upvotes: 4
Views: 182
Reputation: 533530
Keeping things as simple as possible.
public class Threads {
public static class MyRunnable implements Runnable {
public void run() {
try {
for (int i = 0; i < 20; ++i) {
Thread.sleep(500);
System.out.print(i + "\n" + "..");
}
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
}
}
public static void main(String... a) throws InterruptedException {
Thread x = new Thread(new MyRunnable());
Thread y = new Thread(new MyRunnable());
x.start();
y.start();
Thread.sleep(2000);
y.interrupt();
Thread.sleep(2000);
x.interrupt();
}
}
Upvotes: 2
Reputation: 10286
DISCLAIMER: this answer has a tutorial character.
BASIC APPROACH: we initially keep things simple and do not deal with the interruption during the Thread.sleep
method. Essentially, you should have an externally settable variable over which the run method checks at every iteration of the loop; then you can set that variable to gracefully terminate the run()
method. Please note how this idiom can be easily used for languages other than Java.
For example:
public class MyThreadedClass extends Thread {
private volatile boolean completed = false;
public void setCompleted() {
this.completed = true;
}
public void run()
{
while (!completed) {
// do anything you fashion
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
MyThreadedClass y = new MyThreadedClass();
x.start();
y.start();
x.setCompleted(); // will complete as soon as the latest iteration finishes
...
}
}
COMMENTS: The volatile flag tells the compiler that completed
may (and will) be changed outside the control of the run()
function, i.e. another thread may change it. Otherwise the iterative check in the loop may be incorrectly optimized according to the sole synchronous behavior of the class.
In your particular run()
case, we exploit the for
loop, so our approach translates into the following:
public void run()
{
try {
for(int i=0;i<20 && !completed;++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
}
} catch(Exception e) {
e.printStackTrace();
}
}
COMMENTS: as it is pretty obvious, you may have to wait up to 500 millis due to the sleep call. But if, in general, your code has to perform operations that alter the state of variables (in particular, if such variables are shared between multiple threads!), in this way you do not leave those variables in an incorrect state. In practice, you can properly handle a transaction since you control the termination. This obviously assumes that, at the end of each iteration of the loop, the variables state is consistent.
Let us now improve on the basic approach to handle interruption during Thread.sleep
.
COMPLETE ANSWER: this answer involves, from the caller side, the use of the Thread.interrupt()
method, which makes the approach strictly specific to Java.
public class MyThreadedClass extends Thread {
public void run()
{
try {
for(int i=0;i<20 && !this.isInterrupted();++i) {
Thread.sleep(500);
System.out.print(i +"\n"+ "..");
...
// some molassy slow code here, where you may sprinkle isInterrupted()
// checks and consequent break statements
}
} catch(InterruptedException e) {
// do whatever you need to clean things up
} catch(Exception e) {
// handle other exceptions as seen fit
}
}
public static void main(String... args)
{
MyThreadedClass x = new MyThreadedClass();
x.start();
// will complete
// a) as soon as one isInterrupted() check breaks the loop, or
// b) "immediately" during the blocking call to sleep()
x.interrupt();
...
}
}
COMMENTS: in this case, you already have half of your job done by Thread itself. If you only need to interrupt during the Thread.sleep
call, then you do not need to do anything other than handling InterruptedException
to clean up your state, if necessary. If instead you need to interrupt during the "slow" code, you must call this.isInterrupted()
wherever you prefer (possibly in multiple places) and break the loop; the call inside the loop condition is common but not necessary.
More information can be found in the Java Concurrency Interrupts tutorial.
Upvotes: 4
Reputation: 691755
You should interrupt()
the thread. Blocking calls (like sleep()
) will throw an InterruptedException when the thread is interrupted. If you want to stop as fast as possible while in a tight loop, regularly check is the current thread has been interrupted using the isInterrupted()
method.
More information about this in the Java concurrency tutorial.
Upvotes: 2