Нынешние требования к программистам на собеседовании становятся все выше и выше, и чем солиднее фундамент, тем выше вероятность получить предложение. Крупные фабрики по-прежнему очень упорны в фундаменте. вообразите свой потенциал, а затем перейдите к взращиванию вашего.
Помимо алгоритмов, сетей, компьютерных основ и т. д. все больше внимания уделяется многопоточности. Без лишних слов позвольте мне поделиться с вами вопросом.
1. Что такое процесс?
Процесс — это программа, работающая в системе, и когда программа запущена, она становится процессом.
Процесс можно рассматривать как экземпляр выполнения программы. Процесс является независимым объектом для распределения системных ресурсов, и каждый процесс имеет независимое адресное пространство. Один процесс не может получить доступ к переменным и структурам данных другого процесса.Если вы хотите, чтобы один процесс имел доступ к ресурсам другого процесса, вам необходимо использовать межпроцессное взаимодействие, такое как каналы, файлы, сокеты и т. д.
2. Что такое нить?
Это наименьшая единица, которую операционная система может выполнять для планирования операций. Он содержится в процессе и является фактическим операционным блоком в процессе. Поток относится к одному последовательному потоку управления в процессе.Процесс может иметь несколько потоков одновременно, и каждый поток выполняет разные задачи параллельно.
3. Как реализован поток?
1. Наследовать класс Thread
2. Реализуйте интерфейс Runnable
3. Используйте Callable и Future
4.В чем разница между стартами () и RUN () методами в классе потоков?
1.start () метод для запуска потока, действительно многопоточная операция. Затем, не дожидаясь завершения кода тела метода запуска, вы можете перейти непосредственно к следующему коду; чтобы запустить поток, вызвав метод start Thread class(), тогда этот поток находится в состоянии готовности и не выполняется. Затем этот метод вызывает класс Thread run() для завершения его операции запуска, где метод run() вызывает тело потока, которое содержит содержимое этого потока для выполнения, заканчивая метод Run для запуска этого потока для завершения. Затем ЦП планирует другие потоки.
Вызовите метод 2.run() как обычный метод пути. Выполнить процедуру или заказ, дождаться реализации метода ее запуска, продолжить следующий код; только основной программный поток - это поток, который представляет собой только один путь выполнения программы, поэтому нет смысла писать темы .
5. Состояние потока НОВОЕ
Когда new создает объект Thread, он не находится в состоянии выполнения, поскольку метод запуска не вызывается для запуска нового потока, тогда состояние в это время является новым состоянием.
6. Состояние потока RUNNABLE
Объект потока переходит в рабочее состояние через метод запуска. Запущенный поток не может быть выполнен немедленно. Будет ли поток работать или нет, зависит от планирования ЦП. Мы называем это промежуточное состояние исполняемым состоянием (RUNNABLE).
7. Состояние потока RUNNING
Как только процессор выбирает поток из очереди исполняемых задач с помощью опроса или других методов, он может выполнять свой собственный логический код.
8. Состояние потока BLOCKED
Поток ожидает получения блокировки.
Войдите в состояние BLOCKED, например вызов сна или метод ожидания.
Выполнение блокирующей операции ввода-вывода, например, переход в состояние BLOCKED из-за чтения и записи сетевых данных.
Получите ресурс блокировки, чтобы присоединиться к очереди блокировки блокировки и войти в состояние BLOCKED
9. Состояние потока завершено
Завершено — это конечное состояние потока, и в этом состоянии поток не переключится ни в какое другое состояние, и весь жизненный цикл завершен.
Следующие ситуации перейдут в состояние TERMINATED:
Операция потока завершается нормально, завершая жизненный цикл
Ошибка запуска потока неожиданно завершилась
Сбой JVM приводит к завершению всех потоков
10. Диаграмма перехода состояния потока
11.i - исключение с System.out.println()
Образец кода:
public class XkThread extends Thread {
private int i = 5;
@Override
public void run() {
System.out.println("i=" + (i——————) + " threadName=" + Thread.currentThread().getName());
}
public static void main(String[] args) {
XkThread xk = new XkThread();
Thread t1 = new Thread(xk);
Thread t2 = new Thread(xk);
Thread t3 = new Thread(xk);
Thread t4 = new Thread(xk);
Thread t5 = new Thread(xk);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}
}
Хотя метод println() внутренне синхронизирован, операция i———— происходит до входа в println(), поэтому есть вероятность, что он не является потокобезопасным.
Метод RUN выполняется и естественным образом завершается.
Методы stop(), suspend() и возобновить() являются просроченными и недействительными методами, и результаты их использования непредсказуемы.
Большинство операций, которые останавливают поток, используют Thread.interrupt(), что эквивалентно пометке потока меткой остановки. Этот метод не возвращается, чтобы завершить запущенный поток. Для завершения остановки потока необходимо добавить суждение.
17. Прервано и прервано
прервано: чтобы определить, был ли текущий поток прерван, статус будет очищен.
isInterrupted : определяет, был ли поток прерван и не очистит состояние.
18.yield
Откажитесь от текущего ресурса процессора и отдайте его другим задачам, чтобы занять время выполнения процессора. Однако время отказа неизвестно, и возможно, что сразу после отказа сразу будет получен квант времени процессора.
Тестовый код: (эксклюзивный квант времени процессора)
public class XKThread extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for (int i = 0; i < 50000000; i++) {
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("用时 = " + (endTime - beginTime) + " 毫秒! ");
}
public static void main(String[] args) {
XKThread xkThread = new XKThread();
xkThread.start();
}
}
результат:
用时 = 20 毫秒!
Добавьте выход и снова проверьте. (процессор отдает другие ресурсы и тормозит)
public class XKThread extends Thread {
@Override
public void run() {
long beginTime = System.currentTimeMillis();
int count = 0;
for (int i = 0; i < 50000000; i++) {
Thread.yield();
count = count + (i + 1);
}
long endTime = System.currentTimeMillis();
System.out.println("用时 = " + (endTime - beginTime) + " 毫秒! ");
}
public static void main(String[] args) {
XKThread xkThread = new XKThread();
xkThread.start();
}
}
результат:
用时 = 38424 毫秒!
19. Приоритет потока
В операционной системе потоки могут иметь приоритеты.Потоки с более высоким приоритетом получают больше ресурсов ЦП, то есть ЦП ограничены выполнением задач в объектах потока с более высоким приоритетом, но нельзя гарантировать, что они будут иметь более высокий приоритет, поэтому они будут казнен первым. .
Приоритет Java разделен на уровни от 1 до 10. Чем больше число, тем выше приоритет. Размер приоритета по умолчанию равен 5. Выбрасывает за пределы области действия: java.lang.IllegalArgumentException.
20. Функция приоритетного наследования
Приоритет потоков наследуется, например, поток a запускает поток b, а поток b имеет тот же приоритет, что и поток a.
21. Кто быстрее бегает?
Установите уровень приоритета двух потоков, накапливайте числа, см. Кто работает быстрее и введите код.
public class Run extends Thread{
public static void main(String[] args) {
try {
ThreadLow low = new ThreadLow();
low.setPriority(2);
low.start();
ThreadHigh high = new ThreadHigh();
high.setPriority(8);
high.start();
Thread.sleep(2000);
low.stop();
high.stop();
System.out.println("low = " + low.getCount());
System.out.println("high = " + high.getCount());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ThreadHigh extends Thread {
private int count = 0;
public int getCount() {
return count;
}
@Override
public void run() {
while (true) {
count++;
}
}
}
class ThreadLow extends Thread {
private int count = 0;
public int getCount() {
return count;
}
@Override
public void run() {
while (true) {
count++;
}
}
}
результат:
low = 1193854568
high = 1204372373
22. Типы резьбы
Существует два типа потоков Java: один поток пользователя, а другой поток демона.
23. Особенности потоков демона
Поток демона — это специальный поток, который в основном используется для фонового планирования и поддержки работы в программе. Когда в виртуальной машине Java нет потока, отличного от демона, поток демона завершит свою работу с JVM.
24. Типичный поток демона в Java
GC (сборщик мусора)
25. Как настроить поток демона
Thread.setDaemon(true)
PS: Свойство Daemon необходимо установить перед запуском потока, и его нельзя установить после запуска.
25. Будет ли выполняться блок finally в потоке Daemon при выходе из виртуальной машины Java?
Блок finally в потоке Daemon не обязательно выполняется при выходе из виртуальной машины Java.
Пример кода:
public class XKDaemon {
public static void main(String[] args) {
Thread thread = new Thread(new DaemonRunner(),"xkDaemonRunner");
thread.setDaemon(true);
thread.start();
}
static class DaemonRunner implements Runnable {
@Override
public void run() {
try {
SleepUtils.sleep(10);
} finally {
System.out.println("Java小咖秀 daemonThread finally run …");
}
}
}
}
результат:
Нет вывода, что указывает на отсутствие выполнения окончательно.
26. Установите загрузчик класса контекста потока
Получить загрузчик класса контекста потока
public ClassLoader getContextClassLoader()
Установите загрузчик класса потока (может нарушить механизм делегирования родительского класса загрузчика классов Java)
public void setContextClassLoader(ClassLoader cl)
27.join
Присоединение относится к добавлению указанного потока к текущему потоку. Например, присоединение к потоку a приведет к тому, что текущий поток b будет ожидать окончания жизненного цикла a, в течение которого поток b находится в заблокированном состоянии.
28. Что синхронизируется?
Синхронизированное ключевое слово может быть простой стратегией для предотвращения взаимодействия потоков и ошибок согласованности памяти.Если объект виден нескольким потокам, то все операции чтения и записи в паре будут синхронизированы.
29. Какие две важные инструкции jvm включены в синхронизированные?
контролировать вход и монитор выхода
30. Синхронизированное использование ключевых слов?
Может использоваться для украшения блоков кода или методов.
31. Что такое синхронизированная блокировка?
Обычный метод синхронизации ————> Замок является текущим объектом силы.
Метод статической синхронизации ————> Блокировка — это объект класса текущего класса.
Метод синхронизации быстро -----> Конфигурация синхонизированных кронштейнов объекта блокировки.
32. Заголовок объекта Java
Блокировка, используемая синхронизацией, хранится в заголовке объекта Java. Если объект является массивом, виртуальная машина сохраняет заголовок объекта шириной 3 слова (Word), а если объект не является массивом, она сохраняет заголовок объекта шириной 2 слова.
Советы: В 32-битной виртуальной машине ширина слова равна 4 байтам.
33. Длина заголовка объекта Java
34. Структура хранения заголовков объектов Java
JVM 32 хранит конфигурацию по умолчанию Mark Word
35. Изменение состояния Mark Word
Данные, хранящиеся в Mark Word, будут изменяться по мере изменения флага блокировки.
В 64-битной виртуальной машине Mark Word имеет 64-битный размер.
36. Блокировка продвижения и правила продвижения
Java SE 1.6 для повышения производительности блокировки. Введены «смещенные замки» и «облегченные замки».
Блокировки в Java SE 1.6 имеют 4 состояния. Уровни от низкого к высокому: состояние без блокировки, состояние смещенной блокировки, облегченное состояние блокировки и тяжелое состояние блокировки.
Замки могут быть обновлены только но не понижены.
37. Блокировка смещения
В большинстве случаев блокировки не только не являются многопоточными, но и всегда запрашиваются несколько раз одним и тем же потоком. Когда поток обращается к синхронизированному блоку и получает блокировку, идентификатор потока, в котором хранится смещение блокировки, будет записан в заголовке объекта и кадре стека.В будущем потоку не нужно будет выполнять операцию cas для блокировки и разблокировки, когда вход и выход из синхронизированного блока.Проверьте, хранит ли заголовок объекта Mark Word смещенную блокировку, указывающую на текущий поток. Если проверка прошла успешно, это означает, что поток захватил блокировку, если нет, то нужно проверить, установлен ли флаг смещения блокировки в Mark Word в 1 (указывающий текущую блокировку смещения). не установлен, используйте cas для борьбы за блокировку.Если установлен Если он установлен, попробуйте использовать cas, чтобы сместить блокировку заголовка объекта только к текущему потоку.
38. Отключить задержку блокировки смещения
Он включен по умолчанию в java6 и 7, но он не будет активирован до тех пор, пока не пройдет несколько секунд после запуска программы.Если вам нужно закрыть задержку,
-XX:BiasedLockingStartupDelay=0.
39. Как отключить блокировку смещения
Параметр JVM отключает смещенную блокировку: -XX:-UseBiasedLocking=false, тогда программа по умолчанию перейдет в состояние облегченной блокировки.
Советы: Если вы можете определить, что все замки программы обычно в состоянии гонки, вы можете закрыть.
40. Легкий замок
Поток выполняет синхронизированный блок, и теперь jvm создаст место в кадре стека текущего потока для хранения записи блокировки. И скопируйте слово Mark в заголовке объекта в запись блокировки. Затем поток пытается использовать cas для замены Mark Word в заголовке объекта указателем на запись блокировки родного города. Если это удается, текущий поток получает блокировку, если это не удается, это означает, что другие потоки конкурируют за блокировку, и текущий поток пытается использовать вращение, чтобы получить блокировку.
41. Отпирание облегченных замков
Когда легковесный замок будет разблокирован, атомарная операция cas заменит смещенное слово Mark обратно в заголовок объекта. Если ей это удастся, значит, конкуренции нет. Если не получится, значит, конкуренция есть. В это время, замок расширится в тяжеловесный замок.
42. Сравнение преимуществ и недостатков замков
43. Что такое атомная операция
Операция или серия операций, которые нельзя прервать
44. Как Java реализует атомарные операции
В Java атомарные операции реализуются с помощью блокировок и цикла cas.Операция CAS JVM реализуется с помощью инструкции CMPXCHG, предоставляемой процессором. Основная идея реализации spin CAS заключается в циклическом выполнении операций CAS до тех пор, пока они не завершатся успешно.
45. 3 основные проблемы CAS для достижения атомарных операций
Проблема ABA, длительное время цикла потребляет много ресурсов и может гарантировать только атомарную операцию общей переменной.
46. Что такое проблема ABA
проблема:
С момента времени, необходимого для значения операции cas, значение проверки не изменилось, если обновление не изменится, если значение равно A, становится B и становится A, оно найдет использование значения обнаружения волос cas. Оно не изменилось, в факт, становится когда-либо.
решать:
Добавьте номер версии и добавляйте номер версии каждый раз при обновлении, A-B-A -> 1A-2B-3A.
Начиная с jdk1.5, пакет Atomic предоставляет класс AtomicStampedReference для решения проблемы ABA.
47. Время цикла CAS велико и требует много ресурсов.
Если JVM может поддерживать инструкцию паузы, предоставляемую процессором, эффективность в определенной степени повысится.
1. Он может задержать выполнение трубопровода инструкций (деупепроводы), чтобы ЦП не будет потреблять слишком много выполнения ресурсов. Время задержки зависит от конкретной версии реализации, а некоторые процессоры имеют время задержки 0.
Во-вторых, можно избежать опустошения конвейера ЦП из-за конфликтов порядка памяти при выходе из цикла, тем самым повышая эффективность выполнения ЦП.
48. CAS может гарантировать только атомарные операции с общей переменной.
1. Блокировки можно использовать при работе с несколькими общими переменными.
Во-вторых, вы можете объединить несколько общих переменных в одну общую переменную для работы. Например, x=1, k=a, объединить xk=1a, а затем использовать cas для работы с xk.
Советы. Начиная с версии java 1.5, jdk предоставляет класс AtomicReference для обеспечения атомарности между питьевыми объектами, поэтому вы можете поместить несколько переменных в один объект для выполнения операций cas.
49. изменчивое ключевое слово
volatile легко синхронизируется, он обеспечивает «видимость» общих переменных в многопроцессорной разработке.
3-е издание Спецификации языка Java определяет volatile следующим образом. Java позволяет потокам получать доступ к общим переменным. Чтобы обеспечить точное и последовательное обновление общих переменных, потоки должны гарантировать, что монопольная блокировка получает только эту переменную. Если поле объявлено как volatile, все потоки Java Threaded Memory Model видят одно и то же значение переменной.
50. Механизм ожидания/уведомления
Один поток изменяет значение объекта, в то время как другой поток воспринимает изменение и действует соответствующим образом.
51.wait
Функция метода ждать () заключается в том, чтобы поток в настоящее время выполнял код ожидания. Ждать () - это общий метод класса объекта. Этот метод используется для размещения текущего потока в «очереди предварительного выполнения» и выполнить Код в коде, где ждут () находится. Остановить выполнение до уведомления или прерванного.
Поток должен получить блокировку уровня объекта на объекте перед вызовом ожидания. С точки зрения кода он может быть только в синхронизированном методе или синхронному блоке кода. Текущая тема выпускает замок после вызова ждать ().
52.notify
notify() также является общим методом класса Object. Он также вызывается в методе синхронизации или блоке кода синхронизации. Этот метод используется для уведомления других потоков, которые могут активировать блокировку объекта. Если имеется несколько ожидающих потоков, выберите их случайным образом.Один из потоков в состоянии ожидания, уведомите его и дайте ему подождать, чтобы получить блокировку объекта на объекте.
53.notify/notifyAll
notify эквивалентен перемещению потока из очереди ожидания в очередь синхронизации, а notifyAll — перемещению всех потоков из очереди ожидания в очередь синхронизации.
Основное решение заключается в том, что каждый поток хочет связать свое собственное значение и сохранить частные данные потока.
56.ThreadLocal использование
Получите значение текущего потока через get(), установите метод set(T) для установки значения.
public class XKThreadLocal {
public static ThreadLocal threadLocal = new ThreadLocal();
public static void main(String[] args) {
if (threadLocal.get() == null) {
System.out.println("未设置过值");
threadLocal.set("Java小咖秀");
}
System.out.println(threadLocal.get());
}
}
вывод:
未设置过值
Java小咖秀
Советы: значение по умолчанию равно null
57. Решить проблему возврата get() null
Вы можете переопределить метод initialValue() путем наследования.
Код:
public class ThreadLocalExt extends ThreadLocal{
static ThreadLocalExt threadLocalExt = new ThreadLocalExt();
@Override
protected Object initialValue() {
return "Java小咖秀";
}
public static void main(String[] args) {
System.out.println(threadLocalExt.get());
}
}
Выходной результат:
Java小咖秀
58. Блокировка интерфейса
Блокировки предотвращают одновременное совместное использование ресурсов несколькими потоками. До Java 5 программы полагались на синхронизацию для достижения функции блокировки. После Java 5 в параллельный пакет был добавлен интерфейс Lock для реализации функции блокировки.
59. Интерфейс блокировки предоставляет основные функции, которых нет у синхронизированного
60. Блокировка повторного входа
Блокировка, поддерживающая повторный вход, что означает, что блокировка может поддерживать повторную блокировку ресурса потоком. В дополнение к этому замок также поддерживает честный и несправедливый выбор при приобретении замков.
61. Что означает повторный вход?
Повторный вход означает, что любой поток может снова получить блокировку, не будучи заблокированным блокировкой после получения блокировки.
Эта функция в основном решает следующие две проблемы:
1. Блокировка должна определить, является ли поток, получивший блокировку, тем потоком, который в настоящее время занимает блокировку, и если да, то он будет снова успешно получен.
2. Окончательный выпуск выручки. Поток повторно получает блокировку n раз, а затем, после n-го снятия блокировки, другие потоки могут получить блокировку.
62. Блокировка ReentrantLock по умолчанию?
Несправедливая блокировка по умолчанию
Код для доказательства:
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
63. Разница между честной блокировкой и неясной блокировкой
Справедливость или нет, чтобы получить блокировку для него, если блокировка является справедливой, то порядок получения блокировки должен соответствовать запросу в абсолютном хронологическом порядке, то есть FIFO.
64. Блокировка чтения-записи
Блокировки чтения-записи позволяют нескольким потокам чтения получить одновременный доступ, но поток записи и другие потоки записи заблокированы. Блокировки чтения-записи поддерживают одну блокировку чтения и одну блокировку записи, разделяют чтение и запись и улучшают параллелизм.
Класс реализации, обеспечивающий блокировку чтения-записи в Java, называется ReentrantReadWriteLock.
65. Инструмент поддержки блокировки
Определен набор общедоступных статических методов, обеспечивающих самые основные функции блокировки и пробуждения потоков.
66. Интерфейс управления
Обеспечивает методы, аналогичные монитору объекта, используемые в сочетании с блокировкой для реализации режима ожидания / уведомления.
67. Условия использования
Пример кода:
public class XKCondition {
Lock lock = new ReentrantLock();
Condition cd = lock.newCondition();
public void await() throws InterruptedException {
lock.lock();
try {
cd.await();//相当于Object 方法中的wait()
} finally {
lock.unlock();
}
}
public void signal() {
lock.lock();
try {
cd.signal(); //相当于Object 方法中的notify()
} finally {
lock.unlock();
}
}
}
68.ArrayBlockingQueue?
Ограниченная блокирующая очередь, поддерживаемая данными, этот принцип очереди FIFO сортирует элементы. Голова очереди имеет самое долгое существование в очереди, а хвост очереди — самое короткое.
69.PriorityBlockingQueue?
Неограниченная блокирующая очередь, которая поддерживает сортировку по приоритету, но не блокирует производителей данных, а блокирует только потребителей данных, когда нет данных для потребления.
70.DelayQueue?
— это реализация неограниченной очереди блокировки с использованием очереди приоритетов, которая поддерживает отложенную выборку элементов. Элементы в очереди должны реализовывать интерфейс Delayed и Comparable.При создании элемента можно указать, сколько времени потребуется для получения текущего элемента из очереди.
71. Параллельные контейнеры Java, вы знаете несколько?
Версия HashMap, безопасная для параллелизма, java7 использует технологию блокировки сегментов для повышения эффективности параллелизма и по умолчанию разделена на 16 сегментов. Java8 отказывается от блокировки сегментов и использует CAS, в то же время при конфликте хэшей, когда длина связанного списка достигает 8, он будет преобразован в красно-черное дерево. (Подробности см. в коде в jdk)
73.ConcurrentLinkedQueue
Неограниченная потокобезопасная очередь, основанная на связанных узлах, которая использует правило «первым пришел — первым обслужен» для сортировки узлов, когда мы добавляем элемент, он будет добавлен в конец очереди, а когда мы получим элемент, он вернется в начало очереди Elements. Он использует алгоритм cas для достижения. (Подробности см. в коде в jdk)
74. Что такое блокировка очереди?
Блокирующая очередь — это очередь, которая поддерживает две операции добавления, поддерживающие блокирующие методы вставки и удаления.
1. Метод вставки, поддерживающий блокировку: когда очередь заполнена, очередь будет блокировать поток, который вставляет элементы, до тех пор, пока очередь не заполнится.
2. Метод удаления блокировки: когда очередь пуста, поток, который получает элемент, будет ждать, пока очередь не станет непустой.
75. Каковы распространенные сценарии применения блокирующих очередей?
Обычно используемый в сценариях производителя и потребителя, производитель — это поток, который добавляет элементы в очередь, а потребитель — это поток, который берет элементы из очереди. Очередь блокировки — это именно тот контейнер, который хранит производитель и получает потребитель.
Платформа, предоставляемая java7 для параллельного выполнения задач, структура для разделения большой задачи на несколько небольших задач и, наконец, суммирования результатов каждой маленькой задачи для получения результатов большой задачи.
78. Алгоритмы кражи работы
Относится к потоку, перехватывающему задачи из других очередей для выполнения. Когда большая задача разбивается на маленькие задачи, некоторые потоки могут завершить задачу досрочно, в это время лучше помочь другим незавершенным рабочим потокам. В это время можно перейти к другим очередям, чтобы украсть задачи.Для снижения конкуренции обычно используются двухсторонние очереди.Украденный поток берется из головы, а украденный поток выполняется из хвоста.
79. Алгоритм кражи работы имеет недостатки
Преимущества: полное использование потоков для параллельных вычислений, снижение конкуренции между потоками.
Недостатки: В некоторых случаях все же есть конкуренция, например двухсторонняя очередь только на одно задание. Это потребляет больше ресурсов.
80. Атомарные операции обновляют базовые типы в Java. Какие классы предоставляет пакет Atomic?
AtomicBoolean: логический тип атомарного обновления
AtomicInteger: формирование атомарного обновления
AtomicLong: Atomic Update Long Integer
81. Атомарные операции обновляют массивы в Java. Какие классы предоставляет пакет Atomic?
AtomicIntegerArray: атомарное обновление элементов в целочисленных данных.
AtomicLongArray: атомарное обновление элементов в массиве длинных целых чисел.
AtomicReferenceArray: атомные обновления питьевой типы элементов массива
AtomicIntegerArray: в основном обеспечивает атомарный способ обновления целого числа в массиве.
82. Атомарные операции обновляют ссылочные типы в Java. Какие классы предоставляет пакет Atomic?
Если атому необходимо обновить несколько переменных, ему необходимо использовать ссылочный тип.
AtomicReference : тип ссылки атомарного обновления
AtomicReferenceFieldUpdater: Atomic обновляет поля в ссылочных типах.
AtomicMarkableReference: атомные обновления ссылочных типов с отмеченными битами. Марка бита представлена логическим типом, а метод строительства является AtomicMarkableReereference (V Intalref, Boolean Iatealmark)
83. Класс поля обновления атомарной операции в Java. Какие классы предоставляет пакет Atomic?
AtomiceIntegerFieldUpdater: средство обновления, которое атомарно обновляет целочисленные поля.
AtomiceLongFieldUpdater: средство обновления, которое атомарно обновляет длинные поля.
AtomiceStampedFieldUpdater: Atomice обновляет ссылочный тип номером версии, преобразовывая целочисленное значение
84. Какие из наиболее распространенных классов инструментов для обработки параллелизма предоставляются в пакете параллелизма JDK?
Обеспечить средства контроля параллелизма: CountDownLatch, CyclicBarrier, Semaphore
Обмен данными потока: Обменник
85.CountDownLatch
Позволяет одному или нескольким потокам ожидать завершения операций другими потоками.
Конструктор CountDownLatch принимает в качестве счетчика параметр типа int.Если вы хотите дождаться завершения n точек, передайте n.
Два важных метода:
countDown() : при вызове n уменьшается на 1.
await() : вызов блокирует текущий поток, пока n не станет равным 0.
await(long time,TimeUnit unit) : после ожидания в течение определенного времени он больше не будет блокировать текущий поток.
Советы: счетчик должен быть больше или равен 0. Когда оно 0, a ждать не будет блокировать текущий поток.
Он не предоставляет функции для повторного инициализации или изменения значения внутреннего счетчика.
86.CyclicBarrier
Перерабатываемый барьер.
Пусть группа потоков будет заблокирована, когда они достигнут барьера (также называемого точкой синхронизации), и барьер не откроется, пока последний поток не достигнет барьера, а все потоки, заблокированные барьером, продолжат работу.
Конфигурация CyclicBarrier по умолчанию — CyclicBarrier(int parities), и ее параметр указывает количество потоков, перехваченных барьером.Каждый поток вызывает метод await, чтобы сообщить CyclicBarrier, что я достиг барьера, после чего текущий поток блокируется.
87. Разница между CountDownLatch и CyclicBarrier
Защелка обратного отсчета:
Счетчик: Счетчик можно использовать только один раз.
Ожидание: один или несколько потоков ожидают завершения n других потоков перед выполнением.
Циклический барьер:
Счетчик: счетчик можно сбросить (через метод reset()).
Ожидание: n потоков ожидают друг друга, все потоки должны ждать до завершения любого из них.
88.Semaphore
Он используется для управления количеством потоков, одновременно обращающихся к ресурсам, и для обеспечения разумного доступа к общедоступным ресурсам путем координации каждого потока.
Сценарии приложений: контроль потока, особенно сценарии приложений с ограниченными общественными ресурсами, такие как ссылки на данные, ограничение тока и т. Д.
89.Exchanger
Exchanger — это класс инструментов для совместной работы потоков, предоставляющий точку синхронизации, в которой два потока могут обмениваться данными друг с другом. Например, когда первый поток выполняет метод exchange(), он всегда будет ждать выполнения обмена вторым потоком.Когда оба потока достигают точки синхронизации, они могут обмениваться данными.
Вообще говоря, чтобы избежать ситуации постоянного ожидания, вы можете использовать exchange(V x, long timeout, TimeUnit unit) для установки максимального времени ожидания.
Обменник можно использовать для генетических алгоритмов.
90. Зачем использовать пулы потоков
Пулы потоков могут использоваться практически любой программой, которой необходимо выполнять задачи асинхронно или параллельно. Добросовестное использование дает нам следующие преимущества.
Сократите потребление системы: повторно используйте уже созданные потоки, чтобы уменьшить потребление ресурсов, вызванное созданием и уничтожением потоков.
Повышение скорости отклика: при поступлении задач задачи можно выполнять немедленно, не дожидаясь создания потоков.
Обеспечьте управляемость потоком: его можно разумно выделить, настроить и контролировать с помощью настройки.
91. Рабочий процесс пула потоков
1. Определите, все ли потоки в основном пуле потоков выполняют задачи, нет -> создайте новый рабочий поток для выполнения задачи. Да -> перейти к следующему процессу.
2. Определить, заполнена ли рабочая очередь, нет -> новая задача сохраняется в этой рабочей очереди, да -> перейти к следующему процессу.
3. Определить, все ли потоки в пуле потоков работают, нет -> создать новый рабочий поток для выполнения задачи,
Да -> перейти к следующему процессу.
4. В соответствии с установленной политикой для решения задач, которые не могут быть выполнены.
92. Какие параметры для создания пула потоков и каковы их функции?
public ThreadPoolExecutor( int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1. corePoolSize: размер пула основных потоков. Когда задача отправляется, пул потоков создает поток для выполнения задачи. Даже если другие бездействующие основные потоки могут выполнять новые задачи, они будут созданы. Дождитесь числа число выполняемых задач превышает размер ядра потока. Создание не будет продолжено.
2.maximumPoolSize: максимальное количество пулов потоков, максимальное количество потоков, которое можно создать, если очередь заполнена, а количество уже созданных потоков меньше максимального количества потоков, для выполнения будет создан новый поток. задание. Если это неограниченная очередь, этот параметр практически бесполезен.
3.keepAliveTime: время поддержания потока. После того, как рабочий поток пула потоков простаивает, он будет поддерживаться. Поэтому, если есть много задач и время выполнения каждой задачи короткое, время может быть увеличено для улучшения использования потока. .
4.unit: единица времени поддержки потока, дни (DAYS), часы (HOURS), минуты (MINUTES, миллисекунды, MILLISECONDS), микросекунды (MICROSECONDS), наносекунды (NANOSECONDS)
5.workQueue: очередь задач, которая содержит блокирующую очередь задач, ожидающих выполнения.
Как правило, можно выбрать следующие очереди блокировки:
ArrayBlockingQueue: ограниченная очередь блокировки на основе массива.
LinkedBlockingQueue: очередь блокировки на основе связанного списка.
SynchronizedQueue: блокирующая очередь, в которой не хранятся элементы.
PriorityBlockingQueue: очередь блокировки с приоритетом.
6. threadFactory: Установите фабрику для создания потоков.Вы можете установить более значимое имя для каждого созданного потока через фабрику потоков.
Обработчик: Стратегия насыщения также называется стратегией отрицания. Когда пулы очереди и резьбы заполнены, что достигло насыщенности. Таким образом, необходимость в стратегиях для решения новых задач. Стратегия по умолчанию abortpolicy.
AbortPolicy: создает исключение напрямую.
CallerRunsPolicy: поток, в котором вызывающая сторона должна выполнить задачу.
DiscardOldestPolicy: Отменить самую последнюю задачу в очереди и выполнить текущую задачу.
DiscardPolicy: не обрабатывать, просто выбросить.
Конечно, вы можете реализовать пользовательскую стратегию интерфейса RejectedExecutionHandler в соответствии со сценарием вашего собственного приложения.
93. Отправляйте задачи в пул потоков
Задачи могут быть представлены двумя способами: выполнить () и отправить ().
execute(): возвращаемого значения нет, поэтому невозможно судить об успешном выполнении задачи.
submit(): используется для отправки задач, требующих возвращаемого значения. Пул потоков возвращает объект типа future, который можно использовать для определения успешности выполнения задачи, а возвращаемое значение можно получить через get() будущего.Метод get() блокирует текущий поток до тех пор, пока задача завершена. get(long timeout, TimeUnit unit) может установить время супермаркета.
94. Закройте пул потоков
Пул потоков может быть закрыт с помощью shutdown() или shutdownNow(). Их принцип состоит в том, чтобы пройти рабочие потоки в пуле потоков, а затем вызвать прерывание потока один за другим, чтобы прервать поток, поэтому задача, которая не может ответить на терминал, может никогда не остановиться.
shutdownNow сначала устанавливает состояние пула потоков в STOP, затем пытается остановить все выполняющиеся или приостановленные потоки и возвращает список задач, ожидающих выполнения.
shutdown просто устанавливает состояние пула потоков в состояние отключения, а затем прерывает все потоки, которые не выполняют задачи.
IsShutdown вернет true всякий раз, когда вызывается одна из двух функций, а isTerminaed вернет true, когда все задачи будут закрыты.
Вообще говоря, метод shutdown вызывается для закрытия пула потоков.Если задачу не нужно выполнять, метод shutdownNow можно вызвать напрямую.
95. Как правильно настроить пул потоков
Конфигурацию пула потоков можно рассматривать со следующих аспектов.
Задача интенсивно использует процессор, интенсивный ввод-вывод или смешанная
Приоритет задачи, высокий высокий и низкий.
Продолжительность времени выполнения задачи.
Зависимости задач: зависит ли от других системных ресурсов.
Интенсивность ЦП может быть настроена с возможными небольшими потоками, скажем, n+1 потоками.
Тип с интенсивным вводом-выводом может быть настроен с большим количеством потоков, например 2n потоков.
Гибридный тип можно разделить на задачи с интенсивным вводом-выводом и задачи с интенсивным использованием процессора.
Если есть большая разница во времени выполнения двух задач, нет -> пропускная способность декомпозированного выполнения будет выше, чем у последовательного выполнения.
Нет -> Не нужно разлагать.
Вы можете получить количество процессоров через Runtime.GetRuntime (). ДоступныеProcessors ().
Рекомендуется использовать ограниченную очередь для увеличения возможности раннего предупреждения и стабильности системы.
96.Executor
Начиная с JDK5, единица работы и механизм выполнения разделены. Единица работы включает Runnable и Callable, а механизм выполнения предоставляется инфраструктурой Executor.
97. Основные члены фреймворка Executor
ThreadPoolExecutor: может быть создан фабричным классом Executors.
Можно создать три типа ThreadPoolExecutor: SingleThreadExecutor, FixedThreadPool, CachedThreadPool.
ScheduledThreadPoolExecutor : может быть создан исполнителями фабричного класса.
Вы можете создать 2 типа ScheduledThreadPoolExecutor: ScheduledThreadPoolExecutor, SingleThreadScheduledExecutor
Интерфейс Future: Future и класс FutureTask, который реализует интерфейс Future для представления результатов асинхронных вычислений.
Runnable и Callable: оба их класса реализации интерфейса могут выполняться ThreadPoolExecutor или ScheduledThreadPoolExecutor. Runnable не может возвращать результаты, Callable может возвращать результаты.
98.FixedThreadPool
Пул потоков, который может повторно использовать фиксированное количество потоков.
Посмотреть исходный код:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());}
И для corePoolSize, и для maxPoolSize установлено значение nThreads, которое мы установили.
Когда количество потоков в пуле потоков больше, чем corePoolSize, keepAliveTime — это максимальное время, в течение которого избыточные простаивающие потоки ожидают новых задач. По истечении этого времени избыточные потоки будут завершены. Если установлено значение 0, это означает что избыточные простаивающие потоки будут немедленно завершены.
процесс работы:
1. Текущий поток меньше, чем corePoolSize, создайте новый поток для выполнения задач.
2. Текущий запущенный поток равен corePoolSize, и задача добавляется в LinkedBlockingQueue.
3. После того, как поток выполнит задачи в 1, он будет повторно получать задачи из LinkedBlockingQueue для выполнения.
LinkedBlockingQueue в качестве рабочей очереди пула потоков (емкость по умолчанию Integer.MAX_VALUE). Таким образом, это может привести к следующим победам.
1. Когда количество потоков равно corePoolSize, новые задачи будут ждать в очереди, потому что количество потоков в пуле потоков не будет превышать corePoolSize.
2.maxnumPoolSize означает, что это недопустимый параметр.
3.keepAliveTime эквивалентно утверждению, что это также недопустимый параметр.
4. Работающий FixedThreadPool (без выполнения shundown или shundownNow)) не будет вызывать политику отклонения.
5. Поскольку задачи могут добавляться в очередь непрерывно, легко вызвать неработоспособность, когда задач становится все больше и больше.
99.SingleThreadExecutor
является Executor, который использует один рабочий поток.
Посмотреть исходный код:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
corePoolSize и maxnumPoolSize установлены в 1. Остальные параметры такие же, как у FixedThreadPool.
Процесс выполнения и воздействие такие же, как у FixedThreadPool.
100.CachedThreadPool
Пул потоков, который создает новые потоки по мере необходимости.
Посмотреть исходный код:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
Для corePoolSize установлено значение 0, maxmumPoolSize — Integer.MAX_VALUE. KeepAliveTime 60 секунд.
процесс работы:
1. Сначала выполните SynchronousQueue.offer (Выполняемая задача). Если в текущем максимальном пуле есть бездействующий поток, выполняющий SynchronousQueue.poll(keepAliveTIme, TimeUnit.NANOSECONDS), то основной поток выполняет операцию предложения, и операция опроса, выполняемая бездействующим потоком, успешно спаривается, основной поток назначает task в бездействующий поток для выполнения, а метод execute выполняет Done; в противном случае перейдите к шагу 2 ниже.
Если исходный максимальный пул пуст или в нем нет незанятых потоков, то не будет и потоков, выполняющих SynchronousQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS). В этом случае шаг 1 не будет выполнен. В этот момент CachedThreadPool создаст новый поток для выполнения задачи, и метод execute() завершится.
3. После того, как вновь созданный поток на шаге 2 выполнит задачу, будет выполнен SynchronousQueue.poll (keepAliveTime, TimeUnit.NANOSECONDS). Эта операция опроса приведет к тому, что бездействующие потоки будут ждать до 60 секунд в SynchronousQueue. Если основной поток отправляет новую задачу в течение 60 секунд (основной поток выполняет шаг 1), то этот бездействующий поток выполнит новую задачу, отправленную основным потоком; в противном случае этот бездействующий поток завершится. Поскольку бездействующие потоки, бездействующие в течение 60 секунд, завершаются, CachedThreadPool, который остается бездействующим в течение длительного времени, не будет использовать никаких ресурсов.
В целом подходит для коротких, объемных задач.
Ссылаться на:
"Основная технология многопоточного программирования Java"
«Подробное объяснение программирования с высокой степенью параллелизма на Java»
Искусство параллельного программирования на Java
Организовано блогерами + оригинальные вопросы для интервью из 150 000 слов, включая 17 тем. Подпишитесь на «Java Little Coffee Show» и ответьте на «Интервью», чтобы получить заметки об интервью с Java Little Coffee Show.pdf.