且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为什么再次调用Thread.start时会发生IllegalThreadStateException

更新时间:2022-03-05 20:38:32


我怎么能每次杀死或停止线程,以解决这个问题?

how could I kill or stop the thread each time, to get around this problem?

答案是,你可以T。一旦启动,可能无法重新启动 Thread 。对于 javadoc 中明确记录了这一点。 code>发。相反,你真正想要做的是 new 每次你进入循环时 RemoveNonPrime 的一个实例。

The answer is, you can't. Once started, a Thread may not be restarted. This is clearly documented in the javadoc for Thread. Instead, what you really want to do is new an instance of RemoveNonPrime each time you come around in your loop.

您的代码中还有其他一些问题。
首先,您需要在再次使用之前增加 p

You have a few other problems in your code. First, you need to increment p before using it again:

for(int i = 0; i < cores; i++){
    t[i] = new removeNonPrime(f,p); //<--- BUG, always using p=2 means only multiples of 2 are cleared
}

其次,您可能是多线程的,但您不是并发的。您拥有的代码基本上只允许一次运行一个线程:

Second, you might be multithreaded, but you aren't concurrent. The code you have basically only allows one thread to run at a time:

while(p <= (int)(Math.sqrt(N))){
    t[p%cores].start();//
    try{
        t[p%cores].join(); //<--- BUG, only the thread which was just started can be running now
    }catch(Exception e){}
    //get the next prime
    p++;
    while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
}

只需我0.02美元,但你想要做的可能会奏效,但是用于选择下一个最小素数的逻辑并不总是选择素数,例如,如果其他线程中的一个尚未处理该数组的那部分。

Just my $0.02, but what you are trying to do might work, but the logic for selecting the next smallest prime will not always pick a prime, for example if one of the other threads hasn't processed that part of the array yet.

这是使用ExecutorService的方法,有一些空白(...),你必须填写:

Here is an approach using an ExecutorService, there are some blanks (...) that you will have to fill in:

/* A queue to trick the executor into blocking until a Thread is available when offer is called */
public class SpecialSyncQueue<E> extends SynchronousQueue<E> {
    @Override
    public boolean offer(E e) {
        try {
            put(e);
            return true;
        } catch (InterruptedException ex) {
            Thread.currentThread().interrupt();
            return false;
        }
    }
}

ExecutorService executor = new ThreadPoolExecutor(cores, cores, new SpecialSyncQueue(), ...);
void pruneNonPrimes() {
    //...
    while(p <= (int)(Math.sqrt(N))) {
        executor.execute(new RemoveNonPrime(f, p));
        //get the next prime
        p++;
        while(p<=(int)(Math.sqrt(N))&&f[p]==0)p++;
    }


    //count primes
    int total = 0;
    System.out.println();

    for(int j=0; j<f.length;j++){
        if(f[j]!=0){
            total++;
        }
    }
    System.out.printf("Number of primes up to %d = %d",f.length,total);
}



class RemoveNonPrime extends Runnable {
    int k;
    int arr[];

    public RemoveNonPrime(int arr[], int k){
        this.arr = arr;
        this.k = k;
    }

    public void run(){
        int j = k*k;
        while(j<arr.length){
            if(arr[j]%k == 0)arr[j]=0;
            j+=k;
        }
    }
}