我有三个线程Producer,Processor,Consumer,并且都有阻塞队列来共享它们之间的数据。我想加入这些线程,我正在使用未来,所以代码看起来像 -
public class Test {
private static class Producer implements Runnable {
private final BlockingQueue<Integer> queue;
private Producer(BlockingQueue<Integer> queue) {
this.queue = checkNotNull(queue);
}
@Override public void run() {
try {
int i = 0;
while (++i < Integer.MAX_VALUE) {
addEntry(i);
}
} finally {
addEntry(-1);
}
}
private void addEntry(int i) {
try {
queue.put(i);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
private static class Processor implements Runnable {
private final BlockingQueue<Integer> readQueue;
private final BlockingQueue<Integer> writeQueue;
private Processor(BlockingQueue<Integer> readQueue, BlockingQueue<Integer> writeQueue) {
this.readQueue = checkNotNull(readQueue);
this.writeQueue = checkNotNull(writeQueue);
}
@Override public void run() {
try {
int i = readQueue.take();
while (i != -1) {
writeQueue.put(i);
i = readQueue.take();
if(i==1000){
throw new NullPointerException();
}
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} finally {
addEntry(-1);
}
}
private void addEntry(int i) {
try {
writeQueue.put(i);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
private static class Consumer implements Runnable {
private final BlockingQueue<Integer> queue;
private Consumer(BlockingQueue<Integer> queue) {
this.queue = checkNotNull(queue);
}
@Override public void run() {
try {
int i = queue.take();
while (i != -1) {
System.out.println(i);
i = queue.take();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
public static void main(String[] args) {
BlockingQueue<Integer> readQueue = new ArrayBlockingQueue<>(1000);
BlockingQueue<Integer> writeQueue = new ArrayBlockingQueue<>(1000);
ExecutorService executorService = Executors.newFixedThreadPool(3);
Runnable[] runnables = new Runnable[]{new Producer(readQueue), new Processor(readQueue, writeQueue), new Consumer(writeQueue)};
List<Future<?>> futures = Lists.newArrayList();
for (Runnable runnable : runnables) {
futures.add(executorService.submit(runnable));
}
executorService.shutdown();
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException e) {
executorService.shutdownNow();
Thread.currentThread().interrupt();
} catch( ExecutionException e){
executorService.shutdownNow();
throw new RuntimeException(e);
}finally{
future.cancel(true);
}
}
System.out.println("Done..");
}
}
现在,如果Futute#get()抛出异常(处理器中的NPE),我想停止所有线程(Producer,Processor,Consumer)并正常退出。
我怎么能做到这一点?
答案 0 :(得分:0)
您无法强制线程退出。您只能发出信号并将线程编码为接收信号时退出。您可以使用线程中断作为信号线程退出的方式。如果要在调用executorService.shutdownNow()
时执行线程退出,则线程应在中断时退出。
例如,在Consumer
:
@Override public void run() {
try {
int i = queue.take();
while (i != -1) {
System.out.println(i);
i = queue.take();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
当线程被中断时,它只会再次调用interrupt()
。这没有任何成就。 run
方法收到InterruptedException
时会返回:
@Override public void run() {
try {
int i = queue.take();
while (i != -1) {
System.out.println(i);
i = queue.take();
}
} catch (InterruptedException e) {
System.err.println("Consumer interrupted");
return;
}