Следуйте за мной, чтобы получать последние знания, классические вопросы для интервью и делиться техническими данными
Многопоточность и параллелизм - это собеседование на работе в размере завода будет задать знание, которое включает в себя много точки, очень сложно. Некоторые люди сталкиваются с этими проблемами, немного смущенным, чтобы решить эту ситуацию, подвел обоснованные основы джава многопотативной точки параллелизма. И для того, чтобы в глубине изучения Java многопоточность должна сначала освоить основы, вы можете сделать более глубокие исследования для подготовки к последующему наблюдению каждого модуля. Теперь ADO, пожалуйста, скажите, что вы видите базовые знания, а также последующий анализ исходного кода (synchronize
Основной принцип, принцип пула потоков,Lock
,AQS
, анализ исходного кода, например синхронизация и параллельные контейнеры).
1 Основные понятия
Программа:Это набор компьютерных инструкций, которые хранятся на диске в виде файлов, то есть программа представляет собой статический код.
Процесс:
- Это исполнительная деятельность программы в своем собственном адресном пространстве, а именно основная единица системной программы.
- Процесс — это единица использования ресурсов, планирования и независимой работы.
Резьба:
- представляет собой единый непрерывный поток управления в процессе. Процесс может иметь несколько потоков.
- Поток также называют облегченным процессом.Как и процесс, он имеет независимый контроль выполнения и запланирован операционной системой. Разница в том, что потоки не имеют независимого пространства для хранения, а совместно используют пространство для хранения с другими потоками в процессе, которому они принадлежат. Это делает связь между потоками намного проще, чем процессы.
Отношения между тремя:
- Поток — это меньшая единица операции, на которую делится процесс. Самая большая разница между потоками и процессами заключается в том, что в основном каждый процесс независим, в то время как каждый поток не обязательно, потому что потоки в одном процессе, скорее всего, будут влиять друг на друга.
- С другой точки зрения, процесс относится к категории операционной системы, в основном в тот же период времени, может выполнить более одной программы одновременно, в то время как нить практически одновременно выполняется более одного сегмента программы в та же программа.
Механизм памяти можно посмотреть в статье«Рекомендуемая серия коллекций: статья для понимания виртуальной машины JVM (память, сборка мусора, оптимизация производительности) для решения проблем, возникающих на собеседованиях»
2-х ниточная композиция
Компоненты: виртуальный ЦП, исполняемый код и обрабатываемые данные.
3 Различия между потоками и процессами
Процесс:Приложение относится к работающей системе, оно имеет собственное отдельное пространство памяти;
Резьба:Это относится к процессу выполнения в процессе.Процесс позволяет запускать несколько потоков одновременно, они соответственно выполняют разные задачи, и несколько потоков совместно используют память, что значительно повышает эффективность работы программы;
Основные отличия:
- Каждый процесс требует, чтобы операционная система выделила ему отдельное адресное пространство памяти.
- Все потоки одного и того же процесса находятся в одном адресном пространстве, и эти потоки могут совместно использовать данные. Таким образом, обмен данными между потоками относительно прост, а потребляемая системная нагрузка относительно невелика.
4 Зачем использовать многопоточность
Преимущества использования многопоточности:
- Может выполнять несколько задач одновременно
- Когда функциональная часть программы ожидает некоторых ресурсов и не хочет, чтобы программа приостанавливалась из-за ожидания, тогда можно создать другой поток для выполнения другой работы;
- Многопоточность может минимизировать время простоя ЦП, тем самым улучшая использование ЦП;
5 основная нить
При запуске Java-программы немедленно запускается поток, который выполняет основной метод. Этот поток называется основным потоком программы. Любая программа Java имеет по крайней мере один поток, основной поток.
Основная нить особенная в этом:
- Это поток, который порождает дочерние потоки других потоков;
- Обычно он должен заканчиваться последним, потому что он завершает работу других дочерних потоков.
6 Приоритет потока
Одноядерный компьютер имеет только один ЦП, и каждый поток получает право использовать ЦП по очереди для выполнения задач:
- Потоки с более высоким приоритетом имеют больше шансов получить процессор и наоборот;
- Приоритет представлен целым числом, а диапазон значений составляет от 1 до 10. При нормальных обстоятельствах значение потока по умолчанию равно
- Приоритет равен 5, но его также можно установить или вернуть с помощью методов setPriority и getPriority;
.Thread
Класс имеет следующие три статические константы для указания приоритета:
- MAX_PRIORITY: значение равно 10, что указывает на наивысший приоритет.
- MIN_PRIORITY: значение равно 1, что указывает на самый низкий приоритет
- NORM_PRIORITY: значение равно 5, что указывает на приоритет по умолчанию.
7 Жизненный цикл нити
состояние потока (State
Значение перечисления представляет состояние потока):
-
Новое состояние (NEW):Тема только что создана, еще не запущена.
Thread thread = new Thread()
. -
Запускаемое состояние (RUNNABLE):После создания объекта потока другие потоки (например, основной поток) вызывают объект.
start
метод. Нитки в этом состоянии находятся в бассейне Runnable Thread, ожидающие, чтобы быть выбран по расписанию потока, чтобы получить право использовать CPU. -
Бег:Поток получает ресурс ЦП при выполнении задачи (
run()
метод), в это время, если поток автоматически не откажется от ресурсов ЦП или не войдет поток с более высоким приоритетом, поток будет работать до конца -
Заблокированное состояние (Заблокировано):Когда поток выполняется, он приостанавливается, обычно для ожидания наступления определенного времени (например, готовности ресурса), прежде чем продолжить выполнение.
sleep
,suspend
,wait
и другие методы могут привести к блокировке потока - Ожидание (ОЖИДАНИЕ):Введите состояние потоков необходимо дождаться другого потока, чтобы сделать некоторые конкретные действия (уведомление или прерывание).
-
Тайм-аут ожидания (TIMED_WAITING):Это состояние отличается от
WAITING
, он может вернуться сам через указанное время. -
ЗАВЕРШЕНО:Указывает, что поток завершил выполнение, если поток
run
Выполнение метода завершается или вызываетсяstop
метод, нить умирает. Для потока, который умер, его больше нельзя использоватьstart
метод, чтобы сделать его готовым.
Поток может столкнуться с состоянием блокировки во время выполнения процесса:
- перечислить
join()
иsleep()
метод,sleep()
время закончилось или прервалось,join()
Прерывание, завершение ввода-вывода вернется кRunnable
Статус, ожидание планирования JVM. - перечислить
wait()
, сохраняя поток в пуле ожидания (пул ожидания заблокирован) до тех пор, покаnotify()
/notifyAll()
, поток пробуждается и помещается в пул блокировок (lock block pool), освобождая блокировку синхронизации, чтобы вернуть поток в работоспособное состояние (Runnable) - Добавьте блокировку синхронизации (Synchronized) к потоку, находящемуся в состоянии «Выполняется», чтобы заставить его перейти (блокировать заблокированный пул), и снять блокировку синхронизации, чтобы перейти в состояние «Выполняемый» (Runnable).
8 методов создания потоков
Метод создания резьбы:
- Реализовать интерфейс Runnable, перегружая
run()
, нет возвращаемого значения - Наследовать класс Thread, перезаписать
run()
- Реализуйте интерфейс Callable, создайте поток Thread с возвращаемым значением через FutureTask/Future и выполните его через Executor.
- Используйте Executors для создания ExecutorService, введите Callable или Future
1. Чтобы получить интерфейс Runnable, перегрузитеrun()
, нет возвращаемого значения, существование интерфейса Runnable в основном предназначено для решения проблемы, связанной с тем, что в Java запрещено множественное наследование.
public class ThreadRunnable implements Runnable {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
public class ThreadMain {
public static void main(String[] args) throws Exception {
ThreadRunnable threadRunnable1 = new ThreadRunnable();
ThreadRunnable threadRunnable2 = new ThreadRunnable();
ThreadRunnable threadRunnable3 = new ThreadRunnable();
Thread thread1 = new Thread(threadRunnable1);
Thread thread2 = new Thread(threadRunnable2);
Thread thread3 = new Thread(threadRunnable3);
thread1.start();
thread2.start();
thread3.start();
}
}
2. Наследовать класс Thread и переписатьrun()
, позвонив в Threadstart()
вызовет поток созданияrun()
, код в методе run разных потоков выполняется попеременно. Но так как Java не поддерживает множественное наследование, то наследование класса Thread означает, что этот подкласс не может наследовать другие классы.
public class ThreadCustom extends Thread {
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread() + ":" + i);
}
}
}
public class ThreadTest {
public static void main(String[] args)
{
ThreadCustom thread = new ThreadCustom();
thread.start();
}
}
3. Реализовать интерфейс Callable, создать поток Thread с возвращаемым значением через FutureTask/Future и выполнить его через Executor.Этот метод имеет возвращаемое значение и может быть асинхронным.
public class ThreadCallableCustom {
public static void main(String[] args) throws Exception {
FutureTask<Integer> futureTask = new FutureTask<Integer>(new Callable<Integer>() {
public Integer call() throws Exception {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + ":" + i);
}
return 1;
}
});
Executor executor = Executors.newFixedThreadPool(1);
((ExecutorService) executor).submit(futureTask);
//获得线程执行状态
System.out.println(Thread.currentThread().getName() + ":" + futureTask.get());
}
}
4. Используйте Executors для создания ExecutorService, ввода Callable или Future, подходящего для пула потоков и параллелизма.
public class ThreadExecutors {
private final String threadName;
public ThreadExecutors(String threadName) {
this.threadName = threadName;
}
private ThreadFactory createThread() {
ThreadFactory tf = new ThreadFactory() {
public Thread newThread(Runnable r) {
Thread thread = new Thread();
thread.setName(threadName);
thread.setDaemon(true);
try {
sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
}
return thread;
}
};
return tf;
}
public Object runCallable(Callable callable) {
return Executors.newSingleThreadExecutor(createThread()).submit(callable);
}
public Object runFunture(Runnable runnable) {
return Executors.newSingleThreadExecutor(createThread()).submit(runnable);
}
}
public class ThreadTest {
public static void main(String[] args) throws Exception {
ThreadExecutors threadExecutors = new ThreadExecutors("callableThread");
threadExecutors.runCallable(new Callable() {
public String call() throws Exception {
return "success";
}
});
threadExecutors.runFunture(new Runnable() {
public void run() {
System.out.println("execute runnable thread.");
}
});
}
}
9 Разница между интерфейсом Runnable и интерфейсом Callable
1) Имена методов, которые должны быть реализованы двумя интерфейсами, различны.Метод, который должен реализовать Runnable:run()
, метод, который Callable должен реализовать, этоcall()
.
2) Возвращаемое значение реализованного метода другое, после выполнения задачи Runnable возвращаемого значения нет, а результат асинхронного расчета можно получить после выполнения задачи Callable.
3) Генерация исключений отличается, Runnable не может генерировать исключения, Callable может генерировать исключения.
10 нитей безопасности
Определение безопасности потоков
Когда несколько потоков обращаются к классу (объекту или методу), этот класс всегда может демонстрировать правильное поведение, тогда этот класс (объект или метод) является потокобезопасным (то есть при вызове в многопоточной среде способность правильно обрабатывать общие переменные между несколькими потоками, чтобы функциональность программы выполнялась правильно).
Пример безопасности резьбы
Шаблон Hungry singleton — безопасность потоков
public class EagerSingleton(){
private static final EagerSingleton instance = new EagerSingleton();
private EagerSingleton(){};
public static EagerSingleton getInstance(){
return instance;
}
}
Как решить проблему безопасности потоков?
Его можно заблокировать:
- Синхронизированный код кода: только код, который работает на общих данных, должен быть помещен в синхронизированные
- Синхронизация (синхронизированный) метод: работа с данными общего кода, извлеченными в синхронизированный метод, который может быть
- Блокировка блокировки: добавить блокировку синхронизации
lock()
и снимите блокировку синхронизацииunlock()
11 Что такое deadlock и livelock?
Взаимоблокировка относится к явлению, при котором два или более процессов (или потоков) ждут друг друга из-за конкуренции за ресурсы во время процесса выполнения.Если нет внешней силы, они не смогут продвигаться вперед.
Лайвлоки, задачи или исполнители не блокируются, потому что не выполняются некоторые условия, в результате чего повторяются попытки, сбои, попытки, сбои.
Необходимые условия взаимоблокировки:
- Условие взаимного исключения: так называемое взаимное исключение означает, что процесс может монополизировать ресурсы на определенный период времени.
- Условие запроса и удержания: когда процесс блокируется запросом ресурса, он будет удерживать полученный ресурс.
- Условие отсутствия лишения: процесс получил ресурс и не может быть принудительно лишен, пока он не будет израсходован.
- Условие циклического ожидания: между несколькими процессами формируются отношения ресурсов циклического ожидания.
Решение тупиковой ситуации:
- Отменить все процессы, застрявшие в тупике.
- Отменяйте заблокированные процессы один за другим, пока взаимоблокировка не исчезнет.
- Занятые ресурсы вынуждены один за другим отказываться от заблокированного процесса до тех пор, пока взаимоблокировка не исчезнет. Принудительно лишить заблокированный процесс достаточного количества ресурсов от других процессов, чтобы выйти из заблокированного состояния.
12 Что такое пессимистическая блокировка и оптимистичная блокировка?
1) Пессимистический замок
Пессимистические блокировки всегда предполагают наихудший случай.Каждый раз, когда вы идете за данными, вы думаете, что другие изменят их, поэтому каждый раз, когда вы получаете данные, вы блокируете их, так что другие будут блокировать, пока они не получат блокировку, если вы хочу получить данные..
- Многие такие механизмы блокировки используются в традиционных реляционных базах данных, например блокировки строк, таблиц и т. д., блокировки чтения, записи и т. д., которые блокируются перед выполнением операций.
- Реализация ключевого слова synchronized примитива синхронизации в Java также представляет собой пессимистическую блокировку.
2) Оптимистическая блокировка
Оптимистичная блокировка, по определению, очень оптимистично, забрать данные каждый раз, когда другие не изменяются, поэтому он не будет заблокирован, но когда обновление будет определять, что другие в это время не перешли на обновление данных, вы можете использовать Номер версии механизма. Оптимистичная блокировка подходит для типов приложений для чтения, поэтому вы можете улучшить пропускную способность.
13 Параллельное управление блокировками между несколькими потоками
Параллельное управление блокировками между несколькими потоками, объект блокирует несколько потоков, и каждый поток удерживает блокировку и блокировку класса объекта, которому принадлежит метод. синхронизировано, подождите, уведомите — это инструменты синхронизации, которые есть у любого объекта
Синхронизация и асинхронность блокировок объектов
- Синхронизация: синхронизировано, концепция синхронизации заключается в совместном использовании, и синхронизацию необходимо рассматривать только для общих ресурсов.
- Асинхронный: асинхронный, понятие асинхронности независимо и не подлежит никаким ограничениям друг относительно друга.
Целью синхронизации является безопасность потоков Фактически для безопасности потоков должны быть удовлетворены две характеристики: атомарность (синхронизация) и видимость.
14 изменчивых ключевых слов
Независимая функция, реализующая переменную видимость между несколькими потоками, обеспечивающая видимость памяти и запрещающая перестановку инструкций
Многопоточная модель памяти: основная память, рабочая
память (стек потока), при обработке данных поток будет загружать значение из основной памяти в локальный стек, а затем сохранять его обратно после завершения операции (роль ключевого слова volatile: каждая операция над переменной вызывает загрузку и сохранить).
15 ThreadLocal
Переменные, локальные для потока, с помощью пространства-времени предоставляют независимые копии переменных для каждого потока, чтобы обеспечить безопасность потока без блокировок. Основное решение состоит в том, чтобы позволить каждому потоку завершиться после завершения выполнения, в это время используется метод join().
Применимые сценарии:
- Когда параллелизм не очень высок, производительность блокировки будет лучше.
- В сценариях с высокой степенью параллелизма использование ThreadLocal может в определенной степени уменьшить конкуренцию блокировок.
16 Методы реализации многопоточной синхронизации и взаимоисключения
1) Синхронизация потоков относится к отношениям ограничения между потоками. Выполнение одного потока зависит от сообщения другого потока. Когда он не получает сообщения другого потока, он должен ждать, пока сообщение не прибудет.
Методы синхронизации между потоками можно условно разделить на две категории: пользовательский режим и режим ядра. Как следует из названия:
Режим ядра относится к использованию единства системного объекта ядра для синхронизации, и при его использовании необходимо переключаться между режимом ядра и пользовательским режимом. Методы в режиме ядра:
- событие
- сигнал
- Мьютекс
Пользовательский режим означает, что вам не нужно переключаться в режим ядра, а выполнять операции только в пользовательском режиме. Методы в пользовательском режиме:
- Атомарные операции (например, одна глобальная переменная)
- критическая секция
2) Взаимное исключение потоков относится к исключительности каждого отдельного потока, обращающегося к системным ресурсам общего процесса.
Когда несколько потоков хотят использовать общий ресурс, максимально один поток может использовать его в любой момент времени, а другие потоки, которые хотят использовать ресурс, должны ждать, пока пользователь, занимающий ресурс, освободит ресурс. Взаимное исключение потоков можно рассматривать как особый вид синхронизации потоков.
17 Связь между потоками
Поток является независимым от операционной системы индивидуумом, но между этими индивидуумами, если не посредством специального сотрудничества, не может быть целостной связи между потоками, станет единым целым путь.
Несколько способов общаться между потоками?
Связь между потоками:
- Общая память
- обмен сообщениями
Общая память: в модели параллелизма с общей памятью потоки совместно используют общее состояние программы, а потоки взаимодействуют неявно, записывая и читая общее состояние в памяти. Типичным методом связи с общей памятью является связь через общие объекты.
wait()
и notify()
Или блокировка.
18 Что такое интерфейс Java Lock?
Интерфейс java.util.concurrent.locks.Lock обеспечивает более расширенные операции блокировки строк, чем синхронизированные. Он допускает более гибкую структуру, может иметь совершенно другие свойства и может поддерживать условные объекты нескольких связанных классов. Его преимущества:
- Может сделать замки более справедливыми.
- Потоки могут реагировать на прерывания в ожидании блокировки.
- Вы можете заставить поток попытаться получить блокировку и немедленно вернуться или подождать некоторое время, если блокировка не может быть получена.
- Блокировки можно приобретать и снимать в разных объемах и в разном порядке.
19 Java AQS
AQS, AbstractQueuedSynchronizer, синхронизатор очереди. Это базовая структура (такая как ReentrantLock, ReentreamWritelock, Semaphore и т. д.), и семафор и др. (Doug LEA) ожидают, что он удовлетворит большинство требований синхронизации. Это основной базовый компонент j.u.c и пакета.
Преимущества:
AQS решает многие детали, связанные с реализацией синхронизатора, такие как получение состояния синхронизации, очереди синхронизации FIFO. Создание синхронизатора на основе AQS может принести много преимуществ. Это не только значительно сокращает усилия по внедрению, но и избавляет от конфликтов, происходящих в нескольких местах.
В синхронизаторе, построенном на основе AQS, блокировка может происходить только в один момент, тем самым снижая накладные расходы на переключение контекста и улучшая пропускную способность. В то же время AQS был разработан с учетом масштабируемости, поэтому в J.U.C все синхронизаторы, построенные на AQS, могут получить это преимущество.
20 контейнеров синхронного класса
Что такое синхронный контейнер? Его можно просто понимать как контейнер, который реализует синхронизацию через synchronized.Если есть несколько потоков, вызывающих методы синхронизированного контейнера, они будут выполняться последовательно.
Особенности:
- потокобезопасный
- В некоторых сценариях могут потребоваться блокировки для защиты составных операций.
Общие контейнеры классов синхронизации:
- Например, вектор, хеш-таблица.
- Используйте JDK Collections.synchronized и другие фабричные методы для создания реализаций.
- Нижний уровень заключается в использовании традиционного ключевого слова synchronized для синхронизации методов.
- Невозможно удовлетворить требования к производительности в высоких сценариях параллелизма
21 параллельный контейнер класса
После jdk5.0 предоставляется множество параллельных контейнеров, которые заменяют синхронные контейнеры для повышения производительности.
Ограничения контейнера синхронного класса:
- Все серийно.
- Потокобезопасность достигается, но параллелизм снижается
- В многопоточной среде производительность приложения сильно снижается.
Обычно используемые контейнеры параллельных классов:
- ConcurrentHashMap
- Контейнер копирования при записи
Принцип ConcurrentHashMap
- Сегменты используются внутренне для представления этих различных частей.
- Каждый сегмент эквивалентен небольшой HashTable, и у них есть свои блокировки.
- Целое разделено на 16 сегментов (Segment). То есть одновременные операции модификации, поддерживающие до 16 потоков.
- Это также решение для снижения конкуренции блокировок за счет уменьшения детализации блокировок в многопоточных сценариях.
Контейнер для копирования на запись
Copy-On-Write, или COW, — это стратегия оптимизации, используемая в программировании.
- Разделение чтения и записи, разделение чтения и записи
- окончательная согласованность
- Используйте другую идею открытия пространства для решения конфликтов параллелизма
В JDK есть два типа контейнеров COW:
- CopyOnWriteArrayList: подходит для сценариев, в которых операций чтения гораздо больше, чем операций записи, например кэширования.
- CopyOnWriteArraySet: потокобезопасная неупорядоченная коллекция, ее можно понимать как потокобезопасный HashSet, подходящий для набора. Размер обычно остается небольшим, операций только для чтения гораздо больше, чем операций с переменными, это необходимо для предотвращения конфликтов между потоками во время обхода.
22 параллельных очереди
Параллельная очередь:
- ConcurrentLinkedQueue, высокопроизводительная очередь, ConcurrentLinkedQueue является подходящим выбором, когда многие потоки совместно используют доступ к общей коллекции.
- BlockingQueue, очередь блокировки, — это очередь, которая поддерживает две дополнительные операции и часто используется в сценариях производителя и потребителя.
Параллельная связанная очередь
- Подходит для сценариев с высокой степенью параллелизма
- Безблокировочный способ для достижения высокой производительности в состоянии высокой параллелизма
- Его производительность лучше, чем у BlockingQueue.
- Соблюдайте принцип «первым пришел, первым вышел»
Общие методы:
- И Add(), и offer() являются методами добавления элементов.
- Poll() и peek() извлекают узлы элементов, разница в том, что первый удалит элементы, а второй нет.
Реализация интерфейса BlockingQueue:
- ArrayBlockingQueue: реализация очереди блокировки на основе массива. Внутри ArrayBlockingQueue поддерживается массив фиксированной длины для кэширования объектов данных в очереди. Внутреннее разделение чтения и записи не реализовано, что означает, что производство и потребители не могут быть полностью параллельными. Многие сцены.
- LinkedBlockingQueue: очередь блокировки на основе связанного списка. Подобно ArrayBlockingQueue, она также поддерживает очередь буфера данных (очередь состоит из связанного списка). Причина, по которой LinkedBlockingQueue может эффективно обрабатывать параллельные данные, заключается в том, что ее внутренняя реализация использует отдельные блокировки ( чтение Разделение двух блокировок на запись), чтобы операции производителя и потребителя выполнялись полностью параллельно.
- PriorityBlockingQueue: очередь блокировки на основе приоритета (оценка приоритета определяется объектом Compator, переданным конструктором, то есть объект, переданный в очередь, должен реализовывать интерфейс Comparable). принимает честный замок
- DelayQueue: Очередь со временем задержки, в которой элемент может быть получен из очереди только по достижении указанного времени задержки. Элементы в DelayQueue должны сначала реализовать интерфейс Delayed.DelayQueue — это очередь без ограничений по размеру.Существует множество сценариев применения, таких как удаление кэшированных данных об истечении времени ожидания, обработка времени ожидания задачи, закрытие простаивающих соединений и т. д.
- SynchronousQueue: небуферизованная очередь, данные, сгенерированные производителем, будут напрямую получены потребителем и немедленно использованы.
23 многопоточных шаблона проектирования
- Разработано на основе параллельных шаблонов проектирования
- часть оптимизации дизайна
- Это сводка и абстракция некоторых часто используемых многопоточных структур.
- Каковы общие шаблоны проектирования многопоточности?
24 общих класса Concurrent.util
Защелка обратного отсчета:Используется для прослушивания некоторых операций инициализации, после выполнения инициализации уведомляет основной поток о продолжении работы.
cycilcbarrier:После того, как все нити будут готовы, начинаем вместе.Пока один человек не готов, все ждут.
Общие классы Concurrent.utilОпределение: Реализовать асинхронный обратный вызов, jdk предоставляет пакет реализации для этого сценария, который упрощает вызов Подходит для сценариев: при работе с трудоемкой бизнес-логикой это может эффективно сократить время отклика системы и повысить ее пропускную способность.
Общие классы Concurrent.utilСемафор: семафор, подходящий для большого количества одновременных доступов, используется для управления потоком доступа.
ReentrantLockРеентерабельные блокировки, добавляйте блокировки к частям кода, которые нужно синхронизировать, но не забывайте снимать блокировки в конце, иначе блокировки никогда не будут сняты и другие потоки никогда не попадут.
Блокировка и ожидание/уведомление
- Совместная работа между несколькими потоками требует, чтобы методы объекта wait(), notify(), notifyAll() работали вместе.
- При использовании блокировок вы можете использовать новый класс ожидания/уведомления под названием Condition.
- Это условие для конкретного замка
Несколько условий
- Условие может генерировать больше взаимодействия между многопоточными объектами через блокировку.
- Это заставляет некоторые потоки, которые необходимо разбудить, проснуться, а другие потоки продолжают ждать уведомления.
ReentrantReadWriteLock (блокировка чтения-записи)
- Его ядром является замок, реализующий разделение чтения и записи. Он особенно подходит для того, чтобы больше читать и меньше писать при высоком уровне одновременного доступа, и его производительность намного выше, чем у реентерабельных блокировок.
- Разделите блокировки чтения-записи на блокировки чтения и записи.
- При блокировке чтения несколько потоков могут получать одновременный доступ
- Под блокировкой записи только один за другим последовательный доступ
- Оптимизация блокировки
25 пулов потоков
Причины использования платформы Executor:
- Создание потока new Thread() каждый раз при выполнении задачи потребляет производительность, а создание потока отнимает много времени и ресурсов.
- Потоки, создаваемые вызовом new Thread(), лишены управления, называются дикими потоками и могут создаваться без ограничений.Конкуренция между потоками приведет к чрезмерному занятию системных ресурсов и приведет к параличу системы, а также к частым чередованиям между потоками. потребляет много системных ресурсов.
- Потоки, запущенные с помощью new Thread(), не способствуют расширению, такому как выполнение по времени, обычное выполнение, регулярное выполнение по времени, прерывание потока и т. д.
Режим создания пула потоков:
Общий пул потоков задач
- Метод newFixedThreadPool(int nThreads) создает пул потоков фиксированной длины.
- Каждый раз при отправке задачи создается поток до тех пор, пока не будет достигнуто максимальное количество пулов потоков, после чего размер потока не изменится.
- Когда поток завершается с неожиданной ошибкой, пул потоков пополняется новым потоком.
- Метод newCachedThreadPool() создает кэшируемый пул потоков.
- Если размер пула потоков превышает потребность в обработке, простаивающие потоки автоматически восстанавливаются.
- Когда спрос увеличивается, новые потоки могут добавляться автоматически. Размер пула потоков не ограничен.
- Метод NewsIseLethreadexecuture () создает однопоточный пул резьбы.
- Он создает один рабочий поток для выполнения задач, и если этот поток аварийно завершается, для его замены создается новый.
- Его особенность в том, что он обеспечивает последовательное выполнение задач в соответствии с порядком их размещения в очереди.
Пул запланированных задач
- Метод newScheduledThreadPool(int corePoolSize) создает пул потоков фиксированной длины и выполняет задачи с задержкой или по времени, подобно Timer .
- Метод newSingleThreadExecutor() создает пул потоков с фиксированной длиной 1 и выполняет задачи с задержкой или по времени, подобно Timer .
Как закрыть пул потоков
ThreadPoolExecutor предоставляет два метода закрытия пула потоков, а именно:
- Метод shutdown() не останавливает пул потоков немедленно, а завершается после выполнения всех задач в очереди кэша задач, но никогда не принимает новые задачи.
- Метод shutdownNow() немедленно завершает работу пула потоков, пытается прервать выполнение задачи, очищает очередь кеша задач и возвращает невыполненную задачу.
26 Резюме
Поскольку существует слишком много знаний, связанных с многопоточным параллелизмом в Java, невозможно перечислить их все здесь, но я буду дополнять и улучшать их один за другим в последующих обновлениях, а также включать принципы и анализ на уровне исходного кода. Спасибо за просмотр, если есть ошибки, просьба указать на изменения! !
Вы в порядке, офицеры? Если вам это нравится, проведите пальцем, чтобы нажать 💗, нажмите, чтобы подписаться! ! Спасибо за Вашу поддержку!
Добро пожаловать в публичный аккаунт【Технический блог Ccww] Оригинальная техническая статья была запущена в первый раз