保存状态时使用ThreadPool进行多线程处理

时间:2017-10-24 16:56:36

标签: java multithreading executorservice threadpoolexecutor scheduledexecutorservice

假设我在Queue中有100个Runnable对象。如果我使用一个固定大小为10的ExecutorServicePool,则需要终止10个线程中的至少一个,以便从Queue执行下一个Runnable对象。有没有其他方法可以在特定时间间隔之后从队列中安排下一个Runnable并保存当前Runnable状态以保存在队列末尾有点像循环方式?

1 个答案:

答案 0 :(得分:0)

  

有没有其他方法可以在特定时间间隔之后从队列中安排下一个Runnable并保存当前Runnable状态以保存在队列末尾,有点像循环方式?

我希望我在这里理解这个问题。如果这不是您所说的,请编辑您的问题并提供更多详细信息。

如果您正在谈论保存状态,那么简单的解决方案就是使用ThreadLocal,以便执行器服务中运行的每个线程都可以保存自己的状态。

private final ThreadLocal<State> stateThreadLocal = new ThreadLocal<>() {
   // state initialization if needed
   protected State initialValue() { return new State(); }
};
...
public void run() {
   State state = stateThreadLocal.get();
   // now you can process the job with the state
}

但是,如果您需要关闭http客户端或其他内容,此解决方案不会为您提供控制状态何时发布的机会。

更好的解决方案可能是使用执行程序服务来启动静态工作列表,然后使用您自己的BlockingQueue向工作人员注入作业。

例如,您可以执行以下操作:

private final static int NUM_WORKERS = 10;
private final ExecutorService threadPool = Executors.newFixedThreadPool(NUM_WORKERS);
...

final BlockingQueue<Job> queue = new LinkedBlockingQueue<>();
for (int i = 0; i < NUM_WORKERS; i++) {
    threadPool.submit(new WorkerWithState(queue));
}
// shutdown the queue once the last worker is submitted
threadPool.shutdown();
 ...
// then you submit a number of jobs to your own queue for the workers with state to run
queue.add(new Job(...));
...

你的工人将拥有一个他们将在两次运行之间保持的本地状态字段。

private class WorkerWithState implements Runnable {
   // some state held by the worker
   private SomeState state = new SomeState();
   private final BlockingQueue queue;
   public WorkerWithState(BlockingQueue queue) {
      this.queue = queue;
   }
   public void run() {
      while (!Thread.currentThread().isInterrupted()) {
         try {
            // wait for a job to process
            Job job = queue.take();
            // process the job here using the state
            processJob(job, state);
         } catch (InterruptedException ie) {
            // always a good pattern
            Thread.currentThread().interrupt();
            return;
         }
      }
   }
}

要终止这些worker,你可以在线程池上调用threadPool.shutdownAll(true)来中断它们,或者注入一个常量QUIT_JOB,让它们在作业队列耗尽后自行停止。