首页 文章

生产环境 者消费者请求取消

提问于
浏览
1
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 回答

  • 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

    如果您使用的是Java SE 6,则可以访问JMX类 . 我们发现将它用于我们运行的"shut down"服务很有帮助 .

    实质上,您将服务注册为JMX服务 . 并使用驱动程序类来启动它 .

    在您的实际服务类中,实现您的逻辑,实质上使用无限循环来检查条件是否为真(默认情况下将是这样) .

    创建另一个连接到JMX服务的驱动程序类,并将循环条件的值修改为false . 然后,当您达到循环条件时,它将(正常)关闭并且不处理下一组值 .

相关问题