(удобнее просматривать исходный код на горизонтальном экране мобильного телефона)
Примечание. Часть анализа исходного кода Java основана на версии java8, если не указано иное.
Введение
Пул потоков в Java — сложная штука.Углубленное изучение исходного кода пула потоков может не только улучшить понимание всего параллельного программирования на Java, но и повысить вашу производительность на собеседовании и повысить шансы на поступление .
Эта серия будет разделена на несколько глав. Эта глава, как и первая глава о пулах потоков, даст обзор всей системы пулов потоков.
Архитектура
На приведенном выше рисунке перечислены очень важные интерфейсы и классы в пуле потоков:
(1) Executor, интерфейс верхнего уровня пула потоков;
(2) ExecutorService, вторичный интерфейс пула потоков, делает некоторые расширения Executor и добавляет некоторые функции;
(3) ScheduledExecutorService, расширяющий ExecutorService и добавляющий некоторые функции, связанные с задачами по времени;
(4) AbstractExecutorService, абстрактный класс, реализует некоторые методы с использованием шаблона проектирования методов шаблона;
(5) ThreadPoolExecutor, общий класс пула потоков, который мы также обычно называем пулом потоков, включая реализацию самых основных методов, связанных с операциями пула потоков;
(6) ScheduledThreadPoolExecutor, класс пула потоков запланированных задач, используемый для реализации функций, связанных с запланированными задачами;
(7) ForkJoinPool, новый класс пула потоков, новый класс пула потоков в java7, основанный на теории кражи работы, используемый в сценариях, где большие задачи разбиваются на маленькие задачи и есть бесконечные задачи;
(8) Executors, класс инструментов пула потоков, определяет некоторые методы для быстрой реализации пулов потоков (используйте с осторожностью);
Executor
Интерфейс верхнего уровня пула потоков, который определяет только метод для выполнения задач без возвращаемого значения.
public interface Executor {
// 执行无返回值任务【本篇文章由公众号“彤哥读源码”原创】
void execute(Runnable command);
}
ExecutorService
Вторичный интерфейс пула потоков расширяет Executor, в основном добавляя методы для закрытия пула потоков, выполнения задач с возвращаемыми значениями и выполнения задач в пакетах.
public interface ExecutorService extends Executor {
// 关闭线程池,不再接受新任务,但已经提交的任务会执行完成
void shutdown();
// 立即关闭线程池,尝试停止正在运行的任务,未执行的任务将不再执行
// 被迫停止及未执行的任务将以列表的形式返回
List<Runnable> shutdownNow();
// 检查线程池是否已关闭
boolean isShutdown();
// 检查线程池是否已终止,只有在shutdown()或shutdownNow()之后调用才有可能为true
boolean isTerminated();
// 在指定时间内线程池达到终止状态了才会返回true
boolean awaitTermination(long timeout, TimeUnit unit)
throws InterruptedException;
// 执行有返回值的任务,任务的返回值为task.call()的结果
<T> Future<T> submit(Callable<T> task);
// 执行有返回值的任务,任务的返回值为这里传入的result
// 当然只有当任务执行完成了调用get()时才会返回
<T> Future<T> submit(Runnable task, T result);
// 执行有返回值的任务,任务的返回值为null
// 当然只有当任务执行完成了调用get()时才会返回
Future<?> submit(Runnable task);
// 批量执行任务,只有当这些任务都完成了这个方法才会返回
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException;
// 在指定时间内批量执行任务,未执行完成的任务将被取消
// 这里的timeout是所有任务的总时间,不是单个任务的时间
<T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException;
// 返回任意一个已完成任务的执行结果,未执行完成的任务将被取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException;
// 在指定时间内如果有任务已完成,则返回任意一个已完成任务的执行结果,未执行完成的任务将被取消
<T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
ScheduledExecutorService
В ExecutorService были внесены некоторые расширения, чтобы добавить некоторые функции, связанные с временными задачами, которые в основном включают две категории: однократное выполнение и многократное выполнение.
public interface ScheduledExecutorService extends ExecutorService {
// 在指定延时后执行一次
public ScheduledFuture<?> schedule(Runnable command,
long delay, TimeUnit unit);
// 在指定延时后执行一次
public <V> ScheduledFuture<V> schedule(Callable<V> callable,
long delay, TimeUnit unit);
// 在指定延时后开始执行,并在之后以指定时间间隔重复执行(间隔不包含任务执行的时间)
// 相当于之后的延时以任务开始计算【本篇文章由公众号“彤哥读源码”原创】
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit);
// 在指定延时后开始执行,并在之后以指定延时重复执行(间隔包含任务执行的时间)
// 相当于之后的延时以任务结束计算
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,
long initialDelay,
long delay,
TimeUnit unit);
}
AbstractExecutorService
Абстрактный класс использует шаблон проектирования шаблонного метода для реализации некоторых методов, в основном методов для выполнения задач с возвращаемыми значениями и задач пакетного выполнения.
public abstract class AbstractExecutorService implements ExecutorService {
protected <T> RunnableFuture<T> newTaskFor(Runnable runnable, T value) {
return new FutureTask<T>(runnable, value);
}
protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
return new FutureTask<T>(callable);
}
public Future<?> submit(Runnable task) {
if (task == null) throw new NullPointerException();
RunnableFuture<Void> ftask = newTaskFor(task, null);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Runnable task, T result) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task, result);
execute(ftask);
return ftask;
}
public <T> Future<T> submit(Callable<T> task) {
if (task == null) throw new NullPointerException();
RunnableFuture<T> ftask = newTaskFor(task);
execute(ftask);
return ftask;
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks)
throws InterruptedException, ExecutionException {
// 略...
}
public <T> T invokeAny(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
// 略...
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks)
throws InterruptedException {
// 略...
}
public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks,
long timeout, TimeUnit unit)
throws InterruptedException {
// 略...
}
}
Как видите, здесь метод submit() оборачивает входящую задачу в FutureTask для обработки.Что это? Добро пожаловать в следующие главы.
ThreadPoolExecutor
Класс общего пула потоков, который мы также обычно называем пулом потоков, содержит самые основные реализации методов, связанных с операциями пула потоков.
Здесь находится основная логика реализации пула потоков, такая как создание потока, обработка задач, стратегия отклонения и т. д. Позже мы разберем этот класс отдельно.
ScheduledThreadPoolExecutor
Класс пула потоков временных задач используется для реализации функций, связанных с временными задачами, переноса задач в временные задачи и выполнения их в соответствии с временной стратегией. Позже мы проанализируем этот класс отдельно.
Вопрос. Знаете ли вы, какую очередь использует класс пула потоков задач по времени?
ForkJoinPool
Новый класс пула потоков, новый класс пула потоков в java7, очень похож на модель потоков в Go.Он основан на теории захвата работы и особенно подходит для работы со сценариями сортировки слиянием.
Executors
Класс инструмента пула потоков определяет ряд методов для быстрой реализации пула потоков - newXXX(). Однако руководство Ali не рекомендует использовать этот класс для создания нового пула потоков. Брат Тонг, я так не думаю, поскольку пока вы можете освоить его исходный код. Зная, что его преимущества все еще можно использовать время от времени, мы поговорим об этом позже.
пасхальные яйца
Ни пасхальных яиц, ни радости, сегодняшний вопросКакая очередь используется для реализации пула потоков задач по времени?
Ответ: Очередь с задержкой. Пул потоков Timed Task не использует напрямую DelayQueue в параллельной коллекции, а реализует DelayedWorkQueue сам по себе, но принцип реализации тот же, что и у DelayQueue.
Какая структура данных используется для реализации очереди задержки?
Ответ: Куча (приоритетная очередь используется в DelayQueue, а куча используется приоритетной очередью; куча используется непосредственно DelayedWorkQueue).
Для получения связанного контента об очередях с задержкой, приоритетных очередях и кучах щелкните ссылки ниже, чтобы перейти напрямую:
Анализ исходного кода DelayQueue Dead Java Collection
Анализ исходного кода PriorityQueue мертвой java-коллекции
Пожалуйста, не просите меня снова складывать (сортировать) в интервью!
Добро пожаловать, чтобы обратить внимание на мою общедоступную учетную запись «Брат Тонг читает исходный код», проверить больше статей из серии исходного кода и поплавать в океане исходного кода с братом Тонгом.