我想了解ExecutorService
如何充当它创建的线程池的看门狗。
基本上,据我了解,ExecutorService
只是一个对象,它不是创建其他线程的"线程或进程"。
通常,对于ThreadPoolExecutor
:
threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(2);
// Now, requesting Executor Service to "execute" each submitted Tasks.
threadPoolExecutor.execute(runnable);
ScheduleThreadPoolExecutor
也是如此
scheduledThreadPool = Executors.newSingleThreadScheduledExecutor(threadFactory);
scheduledThreadPool.scheduleAtFixedRate(runnable, 2000, 3000, TimeUnit.MILLISECONDS);
从本质上讲,它们只是对象,它们如何能够 ,例如,"如果线程死亡,则重新启动线程"。
我无法理解这一点,例如,在ScheduledThreadPoolExecutor
的情况下,我们调用方法一次进行定期操作,之后,该对象如何能够管理线程。
我确实研究了代码,我仍然怀疑对象如何管理所有这些?(创建线程池、将作业提交到队列、重新启动线程池中的线程等(
你应该最好看看代码。实际上,大多数执行器都有一个私有嵌套类,它封装了您的Runnable并将其管理在线程中。
Executors.newSingleThreadScheduledExecutor 只需创建一个带有一个线程的ScheduledThreadPoolExecutor。然后,当您推送任务时,它会创建一个ScheduledFutureTask(也封装在RunnableScheduledFuture中(,并在必要时创建一个线程。
固定费率时间表 :
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit) {
...
RunnableScheduledFuture<?> t = decorateTask(command,
new ScheduledFutureTask<Object>(command,
null,
triggerTime,
unit.toNanos(period)));
delayedExecute(t);
return t;
}
延迟执行
private void delayedExecute(Runnable command) {
if (isShutdown()) { // handling the cancellation
reject(command);
return;
}
if (getPoolSize() < getCorePoolSize()) // increase number of thread if necessary
prestartCoreThread();
super.getQueue().add(command); // queue the task to be processed a soon as a task is finished
}
排队后,执行器将逐个取消排队(在单线程执行器的情况下,一个线程的线程池(,最终会创建一个线程,在代码中也称为worker。它将调用之前排队的任务的 run(( 方法:
ScheduledFutureTask.run
public void run() {
if (isPeriodic())
runPeriodic();
else
ScheduledFutureTask.super.run(); // just call run() of your Runnable
}
假设我们之前使用scheduleAtFixedRate提交了一个任务,该任务将被视为周期性任务,并且方法runPeriodic 将调用:
ScheduledFutureTask.runPeriodic
private void runPeriodic() {
boolean ok = ScheduledFutureTask.super.runAndReset(); // call run() from your Runnable
boolean down = isShutdown();
// Reschedule if not cancelled and not shutdown or policy allows
if (ok && (!down ||
(getContinueExistingPeriodicTasksAfterShutdownPolicy() && !isTerminating()))) {
long p = period;
if (p > 0)
time += p;
else
time = now() - p;
ScheduledThreadPoolExecutor.super.getQueue().add((Runnable) this);
}
// This might have been the final executed delayed
// task. Wake up threads to check.
else if (down)
interruptIdleWorkers();
}
这让你对魔术是如何发生的有一个想法。大多数"看门狗"的工作都发生在线程内部,他们自己管理。执行器的工作是确保它的队列始终为空,并通过线程调度和创建任务。 然后,任务的行为通过直接访问执行器由自己处理,这要归功于Java的嵌套类可能性。