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