Home > Enterprise >  Why does the ThreadpoolExecutor code never stop running?
Why does the ThreadpoolExecutor code never stop running?

Time:11-27

I run the code in IntelliJ IDEA and it would not stop. I use exec.shutdownNow() instead and it stops successfully. So, I think is the problem of generator, but I can't figure out what problem it is.

The main method:

public static void main(String[] args) {
    PrimeProducer generator = new PrimeProducer(new ArrayBlockingQueue<>(10));
    ExecutorService exec = Executors.newFixedThreadPool(1);
    exec.execute(generator);

    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    } finally {
        generator.cancel();
    }

    //generator.get();
    exec.shutdown();
}

And the PrimeProducer class:

public class PrimeProducer extends Thread{
    private final BlockingQueue<BigInteger> queue;

    PrimeProducer(BlockingQueue<BigInteger> queue){
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while(!Thread.currentThread().isInterrupted()){
                queue.put(p = p.nextProbablePrime());
            }
        } catch (InterruptedException e) {

        }
    }

    public void cancel(){interrupt();}

    public void get(){
        for(BigInteger i : queue){
            System.out.println(i.toString());
        }
    }
}

CodePudding user response:

You have PrimeProducer extend Thread, but you don't actually use it as a thread, you only use it as a Runnable, which is executed on a thread of the thread pool. The cancel has no effect, because it calls the interrupt() of a different thread than the one that is actually running. When you then call exec.shutdown(), the thread pool will interrupt its threads to signal them they should end, when then means PrimeProducer.run will stop.

Instead, use a volatile boolean to end your run (and implement Runnable instead of extending Thread):

public class PrimeProducer implements Runnable {

    private final BlockingQueue<BigInteger> queue;
    private volatile boolean cancelled;

    PrimeProducer(BlockingQueue<BigInteger> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            BigInteger p = BigInteger.ONE;
            while (!cancelled) {
                queue.put(p = p.nextProbablePrime());
            }
        } catch (InterruptedException e) {

        }
    }

    public void cancel() {
        cancelled = true;
    }

    public void get() {
        for (BigInteger i : queue) {
            System.out.println(i.toString());
        }
    }
}
  •  Tags:  
  • java
  • Related