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服务。
当请求关闭时,如何在每个生产者线程中中断for循环,以便每个线程都不处理尚未处理的ID?我能够让shutDownHook工作,但不确定每个线程如何在run方法中包含逻辑以在关闭请求的情况下退出run()方法。可以通过在外部设置一个布尔变量(AtomicBoolean),每个线程在处理每个id之前检查for循环吗?
据我所知,如果我调用shutdown(),它会执行所有提交的任务然后完成。在这种情况下,由于任务已经在执行程序服务上排队,因此无法停止处理。
如果我调用shutdownNow()而不是shutdown(),它可能会产生意外的结果吗?
答案 0 :(得分:1)
shutdownNow vs shutdown取决于您是否希望首先完成当前正在运行的任务。
如果你想要他们立即停止你会做两件事。首先调用shutdownNow。第二,在run方法中测试线程的中断状态。
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) {
if(Thread.currentThread().isInterrupted()){
//the shutdownNow method has been called (or may a future.cancel(true))
}
data = get data from db for the id
consExec.execute(new Consumer(data));
}
}
}
你可以在这里看到run方法现在知道当前线程已被中断。然后,该run方法可以清理任何数据并退出
答案 1 :(得分:1)
如果您使用的是Java SE 6+,则可以访问JMX个类。我们发现使用它来“关闭”我们运行的服务很有帮助。
实质上,您将服务注册为JMX服务。并使用驱动程序类将其关闭。
在您的实际服务类中,实现您的逻辑,该逻辑本质上使用无限循环来检查条件是否为真(默认情况下是这样)。
创建另一个连接到JMX服务的驱动程序类,并将循环条件的值修改为false。然后当你达到你的循环条件时,它会(正常地)关闭而不会处理下一组值。