Каталог статей серии
Пул потоков Android в первой главе объясняется простым языком (1) Пул потоков Android во
второй главе объясняется простым языком (2)
Расширенный пул потоков
Предисловие
В статье «Пул потоков Android, объясняемая простыми терминами (1)» мы в основном поняли преимущества и недостатки потоков и способы их создания. В соответствии с различными параметрами инициализации настройте примеры пулов потоков, которые больше подходят для проекта. В этой главе подробно объясняется соответствующее развитие пулов потоков. Содержание, пожалуйста, прочтите внимательно.
1. Стратегия создания потока
Время создания потоков в пуле потоков связано с параметрами corePoolSize и workQueue и имеет свои собственные определенные логические правила.
Ситуация с потоком | Стратегия |
---|---|
Количество потоков меньше corePoolSize | Создавайте новые потоки напрямую для обработки новых задач |
Количество потоков больше или равно corePoolSize, а workQueue не заполнен | Кешировать новые задачи |
Количество потоков больше или равно corePoolSize, но меньше maximumPoolSize, и workQueue заполнен | Создавайте новые потоки для обработки новых задач |
Количество потоков больше или равно maximumPoolSize, а workQueue заполнен | Используйте политику отказа для обработки новых задач |
Логическая схема создания потока выглядит следующим образом:
Стратегия восстановления двух потоковых ресурсов
Учитывая, что системные ресурсы ограничены, незанятые потоки, пул потоков которых превышает число corePoolSize, должны быть переработаны. Есть проблема с этой операцией, а именно со сроками утилизации. Текущая реализация заключается в повторном использовании, когда время простоя потока превышает keepAliveTime.
Потоки, отличные от числа основных потоков, могут быть переработаны, а простаивающие потоки в основных потоках также могут быть переработаны. Предпосылка повторного использования заключается в том, что для атрибута allowCoreThreadTimeOut установлено значение true.
public void allowCoreThreadTimeOut(boolean value) {
...
}
Три, стратегия очередей
Как упоминалось в правиле создания потока выше, когда количество потоков больше или равно corePoolSize и workQueue не заполнен, новые задачи кэшируются. Здесь нам нужно подумать, какой тип контейнера использовать для кэширования новой задачи. Благодаря введению документа JDK мы можем узнать, что есть 3 типа контейнеров, доступных для использования, а именно синхронные очереди, ограниченные очереди и неограниченные очереди. Для задач с приоритетом сюда также можно добавить очереди с приоритетом.
Для четырех типов очередей, представленных выше, соответствующие классы реализации следующие:
Класс реализации | Виды | Описание |
---|---|---|
Синхронная очередь | Очередь синхронизации | Очередь не хранит элементы, каждая операция вставки должна ждать, пока другой поток вызовет операцию удаления, иначе операция вставки всегда будет заблокирована |
ArrayBlockingQueue | Ограниченная очередь | Очередь с блокировкой на основе массива, сортировка элементов по принципу FIFO |
LinkedBlockingQueue | Неограниченная очередь | На основе очереди блокировки связанного списка элементы сортируются по принципу FIFO. |
PriorityBlockingQueue | Приоритетная очередь | Очередь с приоритетной блокировкой |
Четыре, стратегия отказа
Как упоминалось в приведенной выше стратегии правила создания потока, когда количество потоков больше или равно maximumPoolSize, а workQueue заполнен или текущий пул потоков закрыт, стратегия отклонения используется для обработки новых задач.
Пул потоков Java предоставляет 4 вида классов реализации стратегии отказа, а именно:
Класс реализации | Описание |
---|---|
AbortPolicy | Отменить новую задачу и выбросить исключение RejectedExecutionException. |
DiscardPolicy | Ничего не делать, просто отказаться от новой задачи |
DiscardOldestPolicy | Отбросьте элемент вверху очереди и выполните новую задачу |
CallerRunsPolicy | Отклоненная задача будет обработана в пуле потоков, который в данный момент выполняется в пуле потоков. Эта стратегия обеспечивает простой механизм управления обратной связью, который может замедлить отправку новых задач. |
Среди вышеперечисленных четырех политик отклонения AbortPolicy - это политика по умолчанию, используемая классом реализации пула потоков. Мы также можем изменить стратегию отклонения пула потоков с помощью следующих методов ThreadPoolExecutor.
public void setRejectedExecutionHandler(RejectedExecutionHandler handler) {
...
}
Пятый, как создается поток
В реализации пула потоков создание потоков выполняется посредством реализации интерфейса фабрики потоков ThreadFactory. По умолчанию будет возвращен объект DefaultThreadFactory класса реализации ThreadFactory.
public static ThreadFactory defaultThreadFactory() {
return new DefaultThreadFactory();
}
/**
* The default thread factory
*/
private static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
/**
* 创建线程设置优先级和线程名
*/
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
Конечно, мы также можем использовать метод setThreadFactory (ThreadFactory threadFactory), мы также можем установить фабрику пользовательских потоков.
подводить итоги
。。。