为什么再次调用Thread.start时会发生IllegalThreadStateException [英] Why does an IllegalThreadStateException occur when Thread.start is called again

查看:115
本文介绍了为什么再次调用Thread.start时会发生IllegalThreadStateException的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

public class SieveGenerator{

static int N = 50;
public static void main(String args[]){

    int cores = Runtime.getRuntime().availableProcessors();

    int f[] = new int[N];

    //fill array with 0,1,2...f.length
    for(int j=0;j<f.length;j++){
        f[j]=j;
    }

    f[0]=0;f[1]=0;//eliminate these cases

    int p=2;

    removeNonPrime []t = new removeNonPrime[cores];

    for(int i = 0; i < cores; i++){
        t[i] = new removeNonPrime(f,p);
    }

    while(p <= (int)(Math.sqrt(N))){
        t[p%cores].start();//problem here because you cannot start a thread which has already started(IllegalThreadStateException)
        try{
            t[p%cores].join();
        }catch(Exception e){}
        //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 Thread{
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=j+arr[k];

    }
}
}

你好我当我运行我的代码时,得到一个 IllegalThreadStateException 我认为这是因为我试图启动一个已经启动的线程。那么我怎么能杀掉
或者每次都停止线程来解决这个问题?

Hi I'm getting an IllegalThreadStateException when I run my code and I've figured it's because I am trying to start a thread that has already been started. So how could I kill or stop the thread each time, to get around this problem?

推荐答案


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

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;
        }
    }
}

这篇关于为什么再次调用Thread.start时会发生IllegalThreadStateException的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆