Многопоточность Flashcards Preview

Java > Многопоточность > Flashcards

Flashcards in Многопоточность Deck (44)
Loading flashcards...
1

Дайте определение понятию “процесс”.

Процесс — это совокупность кода и данных, разделяющих общее виртуальное адресное пространство. Процессы изолированы друг от друга, поэтому прямой доступ к памяти чужого процесса невозможен (взаимодействие между процессами осуществляется с помощью специальных средств). Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.

2

Дайте определение понятию “поток”.

Один поток («нить» или «трэд») – это одна единица исполнения кода. Каждый поток последовательно выполняет инструкции процесса, которому он принадлежит, параллельно с другими потоками этого процесса.

3

Дайте определение понятию “синхронизация потоков”.

Синхронизация относится к многопоточности. Синхронизированный блок кода может быть выполнен только одним потоком одновременно.Java поддерживает несколько потоков для выполнения. Это может привести к тому, что два или более потока получат доступ к одному и тому же полю или объекту. Синхронизация — это процесс, который позволяет выполнять все параллельные потоки в программе синхронно. Синхронизация позволяет избежать ошибок согласованности памяти, вызванных непоследовательным доступом к общей памяти.
Когда метод объявлен как синхронизированный — нить держит монитор для объекта, метод которого исполняется. Если другой поток выполняет синхронизированный метод, ваш поток заблокируется до тех пор, пока другой поток не отпустит монитор.
Синхронизация достигается в Java использованием зарезервированного слова synchronized. Вы можете использовать его в своих классах определяя синхронизированные методы или блоки. Вы не сможете использовать synchronized в переменных или атрибутах в определении класса.

4

Как взаимодействуют программы, процессы и потоки?

Чаще всего одна программа состоит из одного процесса, но бывают и исключения (например, браузер Chrome создает отдельный процесс для каждой вкладки, что дает ему некоторые преимущества, вроде независимости вкладок друг от друга). В каждом процессе может быть создано множество потоков. Процессы разделены между собой (>программы), потоки в одном процессе могут взаимодействовать друг с другом (методы wait, notify, join и т.д.).

5

. В каких случаях целесообразно создавать несколько потоков?

Многопоточные приложения применяются в случаях, когда можно разделить программу на несколько относительно независимых частей. В этом случае чтобы один код не ждал другой их помещают в различные потоки. В качестве примера можно привести программу с графическим интерфейсом — пока выполняются какие-либо длительные вычисления в одном потоке, интерфейс может быть доступен пользователю и не зависать, если он выполняется в другом потоке.

6

Что может произойти если два потока будут выполнять один и тот же код в программе?

Если используются не синхронизированные данные, то может произойти ситуация, когда код работает уже с устаревшими данными. Например, в первом потоке идет изменение каких-либо полей, а в это время второй поток читает эти поля.

7

Что вы знаете о главном потоке программы?

Маленькие программы на Java обычно состоят из одной нити, называемой «главной нитью» (main thread). Но программы побольше часто запускают дополнительные нити, их еще называют «дочерними нитями». Главная нить выполняет метод main и завершается. Аналогом такого метода main, для дочерних нитей служит метод run интерфейса Runnable. Много потоков — много методов main (run()).

8

Какие есть способы создания и запуска потоков?

С помощью класса, реализующего Runnable
С помощью класса, расширяющего Thread
С помощью класса, реализующего java.util.concurrent.Callable

9

Какой метод запускает поток на выполнение?

Thread.start() запускает дочерний поток. Для интерфейса Callable запуск потока осуществляется с помощью метода submit().

10

в Каком методе потока описывается код для выполнения ?

Метод run() или метод call() для дочерних потоков. Метод main() для главного потока.

11

Когда поток завершает свое выполнение?

Поток закончит выполнение, когда завершится его метод run() или call(). Для главного потока это метод main().

12

Как синхронизировать метод?

Или указать в сигнатуре модификатор synchronized или использовать конструкцию synchronized {} внутри метода.

13

Как принудительно остановить поток?

В Java 8 нет метода, который бы принудительно останавливал поток. Никто не гарантирует, что нить можно остановить. Она может остановиться только сама. Java имеет встроенный механизм оповещения потока, который называется Interruption (прерывание, вмешательство).

Класс Thread содержит в себе скрытое булево поле, которое называется флагом прерывания. Установить этот флаг можно вызвав метод interrupt() потока. Проверить же, установлен ли этот флаг, можно двумя способами. Первый способ — вызвать метод bool isInterrupted() объекта потока, второй — вызвать статический метод bool Thread.interrupted(). Первый метод возвращает состояние флага прерывания и оставляет этот флаг нетронутым. Второй метод возвращает состояние флага и сбрасывает его. Заметьте что Thread.interrupted() — статический метод класса Thread, и его вызов возвращает значение флага прерывания того потока, из которого он был вызван. Поэтому этот метод вызывается только изнутри потока и позволяет потоку проверить своё состояние прерывания.

У методов, приостанавливающих выполнение потока, таких как sleep(), wait() и join() есть одна особенность — если во время их выполнения будет вызван метод interrupt() этого потока, они, не дожидаясь конца времени ожидания, сгенерируют исключение InterruptedException.

14

поток-демон”.

Потоками-демонами называются потоки, работающие в фоновом режиме для нашей программы.

В Java процесс завершается тогда, когда завершается последний его поток. Даже если метод main() уже завершился, но еще выполняются порожденные им потоки, система будет ждать их завершения.
Однако это правило не относится к особому виду потоков – демонам. Если завершился последний обычный поток процесса, и остались только потоки-демоны, то они будут принудительно завершены и выполнение процесса закончится. Чаще всего потоки-демоны используются для выполнения фоновых задач, обслуживающих процесс в течение его жизни.

Thread thread = new Thread(new DaemonClass());
thread.setDaemon(true);
System.out.println(thread.isDaemon()); //true

15

Как получить текущий поток?

Thread.currentThread(),

16

монитор

Несколько нитей могут мешать друг другу при обращении к одним и тем же данным. Для решения этой проблемы придуман мьютекс (он же монитор). Он имеет два состояния — объект занят и объект свободен. Монитор(мьютекс) — высокоуровневый механизм взаимодействия и синхронизации потоков, обеспечивающий доступ к неразделяемым ресурсам.

Когда какой-то нити нужен общий для всех нитей объект, она проверяет мьютекс, связанный с этим объектом. Если мьютекс свободен, то нить блокирует его (помечает как занятый) и начинает использование общего ресурса. После того, как она сделала свои дела, мьютекс разблокируется (помечается как свободен).

Если же нить хочет использовать объект, а мьютекс заблокирован, то нить засыпает в ожидании. Когда мьютекс, наконец, освободится занятой нитью, наша нить тут же заблокирует его и приступит к работе. Мьютекс встроен в класс Object и следовательно он есть у каждого объекта.

Когда одна нить заходит внутрь блока кода, помеченного словом synchronized, то Java-машина тут же блокирует мьютекс у объекта, который указан в круглых скобках после слова synchronized. Больше ни одна нить не сможет зайти в этот блок, пока наша нить его не покинет. Как только наша нить выйдет из блока, помеченного synchronized, то мьютекс тут же автоматически разблокируется и будет свободен для захвата другой нитью. Если же мьютекс был занят, то наша нить будет стоять на месте и ждать когда он освободится.

17

приостановить выполнение потока?

Thread.sleep()

18

. В каких состояниях может пребывать поток?

Поток может быть в следующем состоянии: созданный, запущенный, блокированный, остановленный, в режиме ожидания, в режиме ожидания по времени (NEW, RUNNABLE, BLOCKED, TERMINATED, WAITING, TIMED_WAITING).

19

Что является монитором при вызове нестатического и статического метода?

Для нестатического метода — текущий объект this. Для статического метода — объекта типа Class, соответствующий классу, в котором определен этот метод.

20

Что является монитором при выполнении участка кода метода?

Монитором является объект, указанный в блоке synchronized участка кода:
synchronized (synchedList) {
...
synchedList.wait();
...
}

21

Какие методы позволяют синхронизировать выполнение потоков?

К этим методам относятся notify(), notifyAll(), wait(режим ожидания); Метод notify пробуждает один из потоков, который вызвал метод wait() у этого монитора. Метод notifyAll пробуждает все потоки.

22

join

Одна нить (поток) может вызвать метод join() у другой нити. В результате первый поток (который вызвал метод) приостанавливает свою работу и ждет окончания работы второго потока (у объекта которого был вызван метод join()).
threadExample.join();

23

условия вызова метода wait/notify?

Методы должны вызываться на объекте-мониторе только из синхронизированного кода. Поток, который вызывает эти методы должен владеть монитором, иначе будет выдано исключение java.lang.IllegalMonitorStateException.

24

взаимная блокировка”.

Deadlock, он же взаимная блокировка, явление при котором все потоки находятся в режиме ожидания. Чтобы уменьшить шанс появления deadlock’a не рекомендуется использовать методы wait() и notify().

25

Чем отличаются методы interrupt, interrupted, isInterrupted?

Метод interrupt() — устанавливает флаг прерывания потока.
Метод bool isInterrupted() объекта потока возвращает состояние флага прерывания и оставляет этот флаг нетронутым.
Статический метод bool Thread.interrupted() — возвращает состояние флага и сбрасывает его.

26

В каком случае будет выброшено исключение InterruptedException, какие методы могут его выбросить?

Методы, требующие обработку этого исключения: wait, sleep, join. Исключение будет выброшено, если флаг interrupt у потока true.

27

. Модификаторы volatile и метод yield()

Помещение модификатора volatile перед определением переменной заставляет принудительно всегда читать и писать значение только в обычную (медленную) память (а не кэшировать). Записывается как: private volatile boolean varName;

Статический метод Thread.yield() заставляет процессор переключиться на обработку других потоков системы. Метод может быть полезным, например, когда поток ожидает наступления какого-либо события и необходимо чтобы проверка его наступления происходила как можно чаще. В этом случае можно поместить проверку события и метод Thread.yield() в цикл:

28

Что есть в пакете java.util.concurrent

Concurrent Collections — набор коллекций,Queues — неблокирующие и блокирующие очереди с поддержкой многопоточности. Synchronizers — вспомогательные утилиты для синхронизации потоков, мощное оружие в «параллельных» вычислениях. Executors — содержит в себе отличные фрейморки для создания пулов потоков. Locks — представляет собой альтернативные и более гибкие механизмы синхронизации потоков Atomics — классы с поддержкой атомарных операций над примитивами и ссылками.

29

Concurrent Collections

CopyOnWriteArrayList-Потокобезопасный аналог ArrayList
CopyOnWriteArraySet
ConcurrentMap
ConcurrentHashMap - данные представлены в виде сегментов, разбитых по hash'ам ключей. В результате, для доступ к данным лочится по сегментам, а не по одному объекту. В дополнение, итераторы представляют данные на определенный срез времени и не кидают ConcurrentModificationException.
ConcurrentSkipListMap Является аналогом TreeMap с поддержкой многопоточности.
ConcurrentSkipListSet

30

Blocking Queues

BlockingQueue При обработке больших потоков данных через очереди становится явно недостаточно использования ConcurrentLinkedQueue. Если потоки, разгребающие очередь перестанут справляться с наплывом данных, то можно довольно быстро схлопотать out of memory или перегрузить IO/Net настолько, что производительность упадет в разы пока не настанет отказ системы по таймаутам или из за отсутствия свободных дескрипторов в системе. Для таких случаев нужна queue с возможностью задать размер очереди или с блокировками по условиям. Тут то и появляется интерфейс BlockingQueue, открывающий дорогу к целому набору полезных классов. Помимо возможности задавать размер queue, добавились новые методы, которые реагируют по-разному на незаполнение или переполнение queue. Так, например, при добавлении элемента в переполненную queue, один метод кинет IllegalStateException, другой вернет false, третий заблокирует поток, пока не появится место, четвертый же заблокирует поток с таймаутом и вернет false, если место так и не появится. Также стоит отметить, что блокирующие очереди не поддерживают null значения, т.к. это значение используется в методе poll как индикатор таймаута.

ArrayBlockingQueue Класс блокирующей очереди, построенный на классическом кольцевом буфере. Помимо размера очереди, доступна возможность управлять «честностью» блокировок. Если fair=false (по умолчанию), то очередность работы потоков не гарантируется. Более подробно о «честности» можно посмотреть в описании ReentrantLock'a.

LinkedBlockingQueue Блокирующая очередь на связанных нодах, реализованная на «two lock queue» алгоритме: один лок на добавление, другой на вытаскивание элемента. За счет двух локов, по сравнению с ArrayBlockingQueue, данный класс показывает более высокую производительность, но и расход памяти у него выше. Размер очереди задается через конструктор и по умолчанию равен Integer.MAX_VALUE.