سؤال

I'm new to multithreading in java and I can't figure out on how to stop a thread. I have an ArrayList of threads which I want to stop. Here is a snippet of my code:

class PrimeThread implements Runnable {
    public void run() {
        while(flag) {
        //do some stuff
        }
    }
    public void cancel() {
        flag = false;
    }
...
}
Class MainClass {
    public static void stopPrimeThreads() {
        for(int i=0; i<primeThreadList.size(); i++) primeThreadList.get(i).cancel();
    }
}

I try to stop the thread by setting the flag variable to false. The flag variable is a volatile boolean declared in the class itself. I also tried to use an outer class variable as sentinel but that did not work either. Also a non volatile variable does not do the job. When I use the deprecated stop() method I get the behavior I want, but I don't want to use a deprecated method. Does anybody has an idea on how to fix this problem? Am I missing something fundamental? Thanks in advance.

هل كانت مفيدة؟

المحلول

Make internal loop something like

while (flag) {
   // smaller step 1
   if (!flag) break;
   // so on
}

As a side-note, if your internal loop takes very long time, it may indicate you using some sub-optimal algorithm. Though, if you working with very large numbers, long calculation times are unavoidable.

نصائح أخرى

use your cancel method not stop on this line...

primeThreadList.get(i).stop();

like so...

primeThreadList.get(i).cancel();

If you have used a non-volatile field, the JIT can optimise the reading of that field away i.e. becuase you don't modify it in your thread. If you make the field volatile it will ensure you change is always seen.

It's hard to know why this doesn't work, since you don't provide an SSCCE, but you should simply use interrupt(), which is designed for that, and allows stopping a thread even if it's waiting on some blocking method:

public void run() {
    while (!Thread.currentThread().isInterrupted()) {
        ...
    }
}

And to stop the thread:

thread.interrupt();

Of course, whatever the solution you choose, if you have another long-running loop inside the outer loop, the thread won't stop until it checks the value of the interrupted/cancelled flag. Make sure to check the flag as often as possible.

class PrimeThread implements Runnable {
    private volatile boolean flag = true;
    public void run() {
        while(flag) {
        //do some stuff
        }
    }
    public void cancel() {
        flag = false;
    }
...
}
Class MainClass {
    public static void stopPrimeThreads() {
        for(int i=0; i<primeThreadList.size(); i++) primeThreadList.get(i).cancel();
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top