我正在尝试理解其API中提供的java.util.concurrent.Executor
接口的以下示例实现。
class SerialExecutor implements Executor {
final Queue<Runnable> tasks = new ArrayDeque<Runnable>();
final Executor executor;
Runnable active;
SerialExecutor(Executor executor) {
this.executor = executor;
}
public synchronized void execute(final Runnable r) {
tasks.offer(new Runnable() {
public void run() {
try {
r.run();
} finally {
scheduleNext();
}
}
});
if (active == null) {
scheduleNext();
}
}
protected synchronized void scheduleNext() {
if ((active = tasks.poll()) != null) {
executor.execute(active);
}
}
}
这里传递的Runnable实例被包装到另一个Runnable实例中并存储在任务Queue中,然后调用scheduleNext()
。传递的Runnable实例是否(防御性地)复制到其他Runnable实例?如果没有,除了从队列执行下一个Runnables外,有什么用呢?
请澄清我的疑问。
答案 0 :(得分:0)
只有在完成第一项任务后才想scheduleNext()
scheduleNext()
。
将原始Runnable包装到调用它的另一个Runnable中,之后调用join()
是一种方便可靠的方法。
通过这种方式,您可以只使用一个线程来实现生产性使用&#34;和#34;队列管理&#34;。
备选方案是一个单独的后台线程,用于监视当前正在运行的任务(例如,通过{{1}}),然后安排一个新任务。
传递的Runnable实例是否(防御性地)复制到其他Runnable实例?
不是真的。当然会复制指向Runnable的指针,但它仍指向同一个Runnable。这不是&#34;防守&#34;因为Runnable的状态理论上可以在排队时更新。
如果没有,除了从队列中执行下一个Runnables之外,这样做的用途是什么?
为什么这还不够理智?毕竟,必须要这样做。