public class MainClass {
private static final int size = 5;
private ExecutorService prodExec = Executors.newFixedThreadPool(size);
private ExecutorService consExec = Executors.newFixedThreadPool(size);
//main method here
public void start(String[] args) {
for (int index = 0; index < size; index++) {
Runnable producer = new Producer(consExec, listOfIds);
prodExec.execute(producer);
}
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
prodExec.shutdown();
try {
prodExec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ignore) {
}
consExec.shutdown();
try {
consExec.awaitTermination(10, TimeUnit.SECONDS);
} catch (InterruptedException ignore) {
}
}
});
}
}
public class Producer implements Runnable {
private ExecutorService consExec;
private List<Long> list;
public Producer(ExecutorService exec, List<Long> list) {
this.consExec = exec;
this.list = list;
}
public void run() {
for (Long id: list) {
data = get data from db for the id
consExec.execute(new Consumer(data));
}
}
}
public class Consumer implements Runnable {
public void run() {
// call web service
}
}
我想处理用户请求关闭的情况可能是通过按Ctrl C.我认为这可以在关闭钩子中完成 . 但是,如上面的代码所示,每个Producer获取一个ID列表(250可能是?),即调用db来检索ID的数据并将数据提交给消费者线程,然后消费者线程调用Web服务 .
How do I break out of the for loop in each of the Producer thread ,当请求关闭时,每个线程都不处理尚未处理的ID?我能够让shutDownHook工作,但不确定每个线程如何在run方法中包含逻辑以在关闭请求的情况下退出run()方法 . 可能是通过在外部设置一个布尔变量(AtomicBoolean),每个线程在处理每个id之前检查for循环?
据我了解,如果我调用shutdown(),它会执行所有提交的任务然后完成 . 在这种情况下,由于任务已经在执行程序服务上排队,因此无法停止处理 .
如果我调用shutdownNow()而不是shutdown(),它可能会产生意外的结果?
2 回答
shutdownNow vs shutdown取决于您是否希望首先完成当前正在运行的任务 .
如果你想要他们立即停止你会做两件事 . 首先调用shutdownNow . 第二,在run方法中测试线程的中断状态 .
你可以在这里看到run方法现在知道当前线程已被中断 . 然后,该run方法可以清理任何数据并退出
如果您使用的是Java SE 6,则可以访问JMX类 . 我们发现将它用于我们运行的"shut down"服务很有帮助 .
实质上,您将服务注册为JMX服务 . 并使用驱动程序类来启动它 .
在您的实际服务类中,实现您的逻辑,实质上使用无限循环来检查条件是否为真(默认情况下将是这样) .
创建另一个连接到JMX服务的驱动程序类,并将循环条件的值修改为false . 然后,当您达到循环条件时,它将(正常)关闭并且不处理下一组值 .