假设我在Queue中有100个Runnable对象。如果我使用一个固定大小为10的ExecutorServicePool,则需要终止10个线程中的至少一个,以便从Queue执行下一个Runnable对象。有没有其他方法可以在特定时间间隔之后从队列中安排下一个Runnable并保存当前Runnable状态以保存在队列末尾有点像循环方式?
答案 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
,让它们在作业队列耗尽后自行停止。