Reputation: 109
why my thread can't be stopped???
class Threadz {
class runP implements Runnable {
int num;
private volatile boolean exit = false;
Thread t;
public runP() {
t = new Thread(this, "T1");
t.start();
}
@Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
num++;
try {
t.sleep(200);
} catch(InterruptedException e) {}
}
}
public void stop() {
exit = true;
}
}
public static void main(String[] a) {
runP rp = new Threadz().new runP();
if(rp.num == 1) {rp.stop();}
}
}
if i use rp.num == 0, the thread can be stopped immediately. But, why when i changed the rp.num == x (x is any number greater than 0) the thread cannot stop? please help me solve this thing... thanks for any helps.
Upvotes: 5
Views: 128
Reputation: 2886
Checking rp.num == 1
would have to happen exactly at a point where rp.num
is exactly one, which is rather unlikely.
In your main
method, you start a thread which increments num
every 200 ms. Afterwards, you check if num == 1
, but when exactly this code is executed depends on a lot of factors you cannot really control (scheduling of the OS, etc...). This might be after 10 ms (where the value would be 1), but could also be after 300 ms (when the value is already 2). Also when the thread is exactly started is unsure. Therefore it is also possible that your thread only starts after the test. You can easily test this by replacing the check if(rp.num == 1) {rp.stop()};
with a simple print statement System.out.println(rp.num)
. If you additionally wait for some time before printing, you might get a better feeling of what I am talking about.
Supposing you would like to stop a runnable from outside, I suggest to use something like the Observer pattern:
class MyRunnable implements Runnable {
private final MyListener l;
private volatile boolean exit;
int num;
public MyRunnable(MyListener l) {
this.l = l;
exit = false;
}
@Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
l.check(num++);
try {
t.sleep(200);
} catch(InterruptedException e) {}
}
}
public void stop() {
exit = true;
}
}
class MyListener {
private final threshold;
public MyListener(int x) {
this.threshold = x;
}
public void check(MyRunnable r, int num) {
if (num >= threshold)
r.stop();
}
}
and your main method would look something like
public static void main(String[] args) {
MyListener l = new MyListener(1);
Runnable r = new MyRunnable(l);
new Thread(r).start();
}
Upvotes: 0
Reputation: 542
Statement below is getting executed before the thread starts executing the run method.
if(rp.num == 1) {rp.stop();}
Add Thread.sleep before the above statement, it works fine as it will execute this statement after starting the loop.
public static void main(String[] a) {
runP rp = new Threadz().new runP();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(rp.num > 1) {rp.stop();}
}
I have made it >1 to test.
Upvotes: 0
Reputation: 5423
I'm sure if you run the program many many times, It'll be a case when the program actually stops.
The reason is at the time you run the program there is much more chance of executing
if(rp.num == 1) {rp.stop();}
before num++
in your run()
method changes value.
However by chance you may come across a case that the loop in your run method gets executed before that if statement in your main method.
one way to make sure this happens is to continuously checking for the condition:
e.g.
public static void main(String[] a) {
runP rp = new Threadz().new runP();
while(true){
if(rp.num == 1) {
rp.stop();
break;
}
}
}
Upvotes: 0
Reputation: 131496
Because this code is not executed in the run() method of the thread :
runP rp = new Threadz().new runP();
if (rp.num == 1) {
rp.stop();
}
It works with 0 as the default value of int is 0.
But it is not necessarily true in all executions of the application as the thread of runP
could run and incrementnum
before the check : if (rp.num == 0)
Move the stop condition in the run method of the runP thread :
@Override
public void run() {
while(!exit) {
System.out.println(t.currentThread().getName()+": "+num);
num++;
try {
t.sleep(200);
} catch(InterruptedException e) {}
if (rp.num == 1) {
exit = true;
}
}
}
Upvotes: 4