thread yield java что это
Параллелизм Java — методы yield (), sleep () и join ()
Мы можем предотвратить выполнение потока, используя один из следующих методов класса Thread.
Использование метода доходности:
Синтаксис:
// Java-программа для иллюстрации метода yield ()
// в Java
class MyThread extends Thread
for ( int i= 0 ; i 5 ; i++)
public class yieldDemo
public static void main(String[]args)
MyThread t = new MyThread();
for ( int i= 0 ; i 5 ; i++)
// Управление передается дочернему потоку
// После выполнения дочернего потока
// основной поток вступает во владение
Выход:
Вывод может быть разным на разных машинах, но шансы на выполнение потока yield () в первую очередь выше, чем на другом потоке, поскольку основной поток всегда приостанавливает выполнение и дает шанс дочернему потоку (с тем же приоритетом).
Замечания:
// Java-программа для иллюстрации
// метод sleep () в Java
public class SleepDemo implements Runnable
for ( int i = 0 ; i 4 ; i++)
// поток для сна в течение 1000 миллисекунд
public static void main(String[] args) throws Exception
Thread t = new Thread( new SleepDemo());
Thread t2 = new Thread( new SleepDemo());
yield () против сна ()
yield :() указывает на то, что поток не выполняет ничего особенно важного, и, если нужно запустить какие-либо другие потоки или процессы, они могут это сделать. В противном случае текущий поток продолжит работу.
sleep () : заставляет поток определенно прекратить выполнение в течение заданного промежутка времени; если никакой другой поток или процесс не требуется запускать, процессор будет простаивать (и, вероятно, перейдет в режим энергосбережения).
// Java-программа для иллюстрации метода join () в Java
public class JoinDemo implements Runnable
Thread t = Thread.currentThread();
System.out.println( «Current thread: «
// проверяет, жив ли текущий поток
System.out.println( «Is Alive? «
public static void main(String args[]) throws Exception
Thread t = new Thread( new JoinDemo());
// Ожидает 1000мс этой нити, чтобы умереть.
System.out.println( «\nJoining after 1000» +
System.out.println( «Current thread: » +
// Проверяет, жив ли этот поток
System.out.println( «Is alive? » + t.isAlive());
Рекомендации: StackOverflow
Пожалуйста, пишите комментарии, если вы обнаружите что-то неправильное или вы хотите поделиться дополнительной информацией по обсуждаемой выше теме.
Многопоточность в Java – руководство с примерами
Пример одного потока :
Преимущества одного потока :
Что такое многопоточность?
Многопоточность в Java — это выполнение двух или более потоков одновременно для максимального использования центрального процесса.
Многопоточные приложения — это приложения, где параллельно выполняются два или более потоков. Данное понятие известно в Java как многопотоковое выполнение. При этом несколько процессов используют общие ресурсы, такие как центральный процессор, память и т. д.
Все потоки выполняются параллельно друг другу. Для каждого отдельного потока не выделяется память, что приводит к ее экономии. Кроме этого переключение между потоками занимает меньше времени.
Жизненный цикл потока в Java
Жизненный цикл потока :
Стадии жизни потока :
Часто используемые методы для управления многопоточностью Java :
Метод | Описание |
start() | Этот метод запускает выполнение потока, а JVM (виртуальная машина Java) вызывает в потоке метод Run (). |
Sleep(int milliseconds) | Делает поток спящим. Его выполнение будет приостановлено на указанное количество миллисекунд, после чего он снова начнет выполняться. Этот метод полезен при синхронизации потоков. |
getName() | Возвращает имя потока. |
setPriority(int newpriority) | Изменяет приоритет потока. |
yield () | Останавливает текущий поток и запускает другие. |
Например : В этом примере создается поток, и применяются перечисленные выше методы.
Объяснение кода
Вывод
5 — это приоритет потока, а « Thread Running » — текст, который является выводом нашего кода.
Синхронизация потоков Java
В многопоточности Java присутствует асинхронное поведение. Если один поток записывает некоторые данные, а другой в это время их считывает, в приложении может возникнуть ошибка. Поэтому при необходимости доступа к общим ресурсам двум и более потоками используется синхронизация.
В Java есть свои методы для обеспечения синхронизации. Как только поток достигает синхронизированного блока, другой поток не может вызвать этот метод для того же объекта. Все другие потоки должны ожидать, пока текущий не выйдет из синхронизированного блока.
Таким образом, решается проблема в многопоточных приложениях. Один поток ожидает, пока другой не закончит свое выполнение, и только тогда другим потокам будет разрешено их выполнение.
Это можно написать следующим образом:
Пример многопоточности Java
В этом Java многопоточности примере мы задействуем два потока и извлекаем имена потоков.
Пример 1
Объяснение кода
Вывод
Имена потоков выводятся как:
Пример 2
Также мы задействуем два класса:
Объяснение кода
При запуске приведенного выше кода получаем следующие выходные данные:
Вывод
Поскольку у нас два потока, то мы дважды получаем сообщение « Thread started ».
Получаем соответствующие имена потоков.
Выполняется цикл, в котором печатается счетчик и имя потока, а счетчик начинается с « 0 ».
Цикл выполняется три раза, а поток приостанавливается на 1000 миллисекунд.
— Новый;
— Готовый к выполнению;
— Выполняемый;
— Ожидающий;
— Остановленный.
Дайте знать, что вы думаете по этой теме в комментариях. За комментарии, лайки, отклики, дизлайки, подписки огромное вам спасибо!
Пожалуйста, оставьте ваши отзывы по текущей теме статьи. За комментарии, отклики, дизлайки, подписки, лайки огромное вам спасибо!
Thread yield java что это
Every thread has a priority. Threads with higher priority are executed in preference to threads with lower priority. Each thread may or may not also be marked as a daemon. When code running in some thread creates a new Thread object, the new thread has its priority initially set equal to the priority of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.
The following code would then create a thread and start it running:
The following code would then create a thread and start it running:
Every thread has a name for identification purposes. More than one thread may have the same name. If a name is not specified when a thread is created, a new name is generated for it.
Unless otherwise noted, passing a null argument to a constructor or method in this class will cause a NullPointerException to be thrown.
Nested Class Summary
Modifier and Type | Class and Description |
---|---|
static class | Thread.State |
Field Summary
Modifier and Type | Field and Description |
---|---|
static int | MAX_PRIORITY |
Constructor Summary
Method Summary
Modifier and Type | Method and Description |
---|---|
static int | activeCount() |
Methods inherited from class java.lang.Object
Field Detail
MIN_PRIORITY
NORM_PRIORITY
MAX_PRIORITY
Constructor Detail
Thread
Thread
Thread
Thread
Thread
Thread
Thread
If there is a security manager, its checkAccess method is invoked with the ThreadGroup as its argument.
In addition, its checkPermission method is invoked with the RuntimePermission(«enableContextClassLoaderOverride») permission when invoked directly or indirectly by the constructor of a subclass which overrides the getContextClassLoader or setContextClassLoader methods.
The priority of the newly created thread is set equal to the priority of the thread creating it, that is, the currently running thread. The method setPriority may be used to change the priority to a new value.
The newly created thread is initially marked as being a daemon thread if and only if the thread creating it is currently marked as a daemon thread. The method setDaemon may be used to change whether or not a thread is a daemon.
Thread
This constructor is identical to Thread(ThreadGroup,Runnable,String) with the exception of the fact that it allows the thread stack size to be specified. The stack size is the approximate number of bytes of address space that the virtual machine is to allocate for this thread’s stack. The effect of the stackSize parameter, if any, is highly platform dependent.
The virtual machine is free to treat the stackSize parameter as a suggestion. If the specified value is unreasonably low for the platform, the virtual machine may instead use some platform-specific minimum value; if the specified value is unreasonably high, the virtual machine may instead use some platform-specific maximum. Likewise, the virtual machine is free to round the specified value up or down as it sees fit (or to ignore it completely).
Specifying a value of zero for the stackSize parameter will cause this constructor to behave exactly like the Thread(ThreadGroup, Runnable, String) constructor.
Due to the platform-dependent nature of the behavior of this constructor, extreme care should be exercised in its use. The thread stack size necessary to perform a given computation will likely vary from one JRE implementation to another. In light of this variation, careful tuning of the stack size parameter may be required, and the tuning may need to be repeated for each JRE implementation on which an application is to run.
Implementation note: Java platform implementers are encouraged to document their implementation’s behavior with respect to the stackSize parameter.
Method Detail
currentThread
yield
Yield is a heuristic attempt to improve relative progression between threads that would otherwise over-utilise a CPU. Its use should be combined with detailed profiling and benchmarking to ensure that it actually has the desired effect.
It is rarely appropriate to use this method. It may be useful for debugging or testing purposes, where it may help to reproduce bugs due to race conditions. It may also be useful when designing concurrency control constructs such as the ones in the java.util.concurrent.locks package.
sleep
sleep
clone
start
The result is that two threads are running concurrently: the current thread (which returns from the call to the start method) and the other thread (which executes its run method).
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Subclasses of Thread should override this method.
If there is a security manager installed, its checkAccess method is called with this as its argument. This may result in a SecurityException being raised (in the current thread).
If this thread is different from the current thread (that is, the current thread is trying to stop a thread other than itself), the security manager’s checkPermission method (with a RuntimePermission(«stopThread») argument) is called in addition. Again, this may result in throwing a SecurityException (in the current thread).
The thread represented by this thread is forced to stop whatever it is doing abnormally and to throw a newly created ThreadDeath object as an exception.
It is permitted to stop a thread that has not yet been started. If the thread is eventually started, it immediately terminates.
An application should not normally try to catch ThreadDeath unless it must do some extraordinary cleanup operation (note that the throwing of ThreadDeath causes finally clauses of try statements to be executed before the thread officially dies). If a catch clause catches a ThreadDeath object, it is important to rethrow the object so that the thread actually dies.
If there is a security manager installed, the checkAccess method of this thread is called, which may result in a SecurityException being raised (in the current thread).
If the argument obj is null, a NullPointerException is thrown (in the current thread).
The thread represented by this thread is forced to stop whatever it is doing abnormally and to throw the Throwable object obj as an exception. This is an unusual action to take; normally, the stop method that takes no arguments should be used.
It is permitted to stop a thread that has not yet been started. If the thread is eventually started, it immediately terminates.
interrupt
Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown.
If this thread is blocked in a Selector then the thread’s interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector’s wakeup method were invoked.
If none of the previous conditions hold then this thread’s interrupt status will be set.
Interrupting a thread that is not alive need not have any effect.
interrupted
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
isInterrupted
A thread interruption ignored because a thread was not alive at the time of the interrupt will be reflected by this method returning false.
destroy
isAlive
suspend
First, the checkAccess method of this thread is called with no arguments. This may result in throwing a SecurityException (in the current thread).
If the thread is alive, it is suspended and makes no further progress unless and until it is resumed.
resume
First, the checkAccess method of this thread is called with no arguments. This may result in throwing a SecurityException (in the current thread).
If the thread is alive but suspended, it is resumed and is permitted to make progress in its execution.
setPriority
Otherwise, the priority of this thread is set to the smaller of the specified newPriority and the maximum permitted priority of the thread’s thread group.
getPriority
setName
getName
getThreadGroup
activeCount
The value returned is only an estimate because the number of threads may change dynamically while this method traverses internal data structures, and might be affected by the presence of certain system threads. This method is intended primarily for debugging and monitoring purposes.
enumerate
Due to the inherent race condition in this method, it is recommended that the method only be used for debugging and monitoring purposes.
countStackFrames
An invocation of this method behaves in exactly the same way as the invocation
dumpStack
setDaemon
This method must be invoked before the thread is started.
isDaemon
checkAccess
toString
getContextClassLoader
If a security manager is present, and the invoker’s class loader is not null and is not the same as or an ancestor of the context class loader, then this method invokes the security manager’s checkPermission method with a RuntimePermission («getClassLoader») permission to verify that retrieval of the context class loader is permitted.
setContextClassLoader
If a security manager is present, its checkPermission method is invoked with a RuntimePermission («setContextClassLoader») permission to see if setting the context ClassLoader is permitted.
holdsLock
This method is designed to allow a program to assert that the current thread already holds a specified lock:
getStackTrace
If there is a security manager, and this thread is not the current thread, then the security manager’s checkPermission method is called with a RuntimePermission("getStackTrace") permission to see if it’s ok to get the stack trace.
Some virtual machines may, under some circumstances, omit one or more stack frames from the stack trace. In the extreme case, a virtual machine that has no stack trace information concerning this thread is permitted to return a zero-length array from this method.
getAllStackTraces
The threads may be executing while this method is called. The stack trace of each thread only represents a snapshot and each stack trace may be obtained at different time. A zero-length array will be returned in the map value if the virtual machine has no stack trace information about a thread.
If there is a security manager, then the security manager’s checkPermission method is called with a RuntimePermission("getStackTrace") permission as well as RuntimePermission("modifyThreadGroup") permission to see if it is ok to get the stack trace of all threads.
getId
getState
setDefaultUncaughtExceptionHandler
Uncaught exception handling is controlled first by the thread, then by the thread’s ThreadGroup object and finally by the default uncaught exception handler. If the thread does not have an explicit uncaught exception handler set, and the thread’s thread group (including parent thread groups) does not specialize its uncaughtException method, then the default handler’s uncaughtException method will be invoked.
By setting the default uncaught exception handler, an application can change the way in which uncaught exceptions are handled (such as logging to a specific device, or file) for those threads that would already accept whatever «default» behavior the system provided.
Note that the default uncaught exception handler should not usually defer to the thread’s ThreadGroup object, as that could cause infinite recursion.
getDefaultUncaughtExceptionHandler
getUncaughtExceptionHandler
setUncaughtExceptionHandler
A thread can take full control of how it responds to uncaught exceptions by having its uncaught exception handler explicitly set. If no such handler is set then the thread’s ThreadGroup object acts as its handler.
Submit a bug or feature
For further API reference and developer documentation, see Java SE Documentation. That documentation contains more detailed, developer-targeted descriptions, with conceptual overviews, definitions of terms, workarounds, and working code examples.
Copyright © 1993, 2020, Oracle and/or its affiliates. All rights reserved. Use is subject to license terms. Also see the documentation redistribution policy.
Thread yield java что это
Расскажите о модели памяти Java?
Модель памяти Java (Java Memory Model, JMM) описывает поведение потоков в среде исполнения Java. Это часть семантики языка Java, набор правил, описывающий выполнение многопоточных программ и правил, по которым потоки могут взаимодействовать друг с другом посредством основной памяти.
Существует несколько основных правил для отношения happens-before:
Можно выделить несколько основных областей, имеющих отношение к модели памяти:
Видимость (visibility). Один поток может в какой-то момент временно сохранить значение некоторых полей не в основную память, а в регистры или локальный кэш процессора, таким образом второй поток, выполняемый на другом процессоре, читая из основной памяти, может не увидеть последних изменений поля. И наоборот, если поток на протяжении какого-то времени работает с регистрами и локальными кэшами, читая данные оттуда, он может сразу не увидеть изменений, сделанных другим потоком в основную память.
С точки зрения Java все переменные (за исключением локальных переменных, объявленных внутри метода) хранятся в главной памяти, которая доступна всем потокам, кроме этого, каждый поток имеет локальную—рабочую—память, где он хранит копии переменных, с которыми он работает, и при выполнении программы поток работает только с этими копиями. Надо отметить, что это описание не требование к реализации, а всего лишь модель, которая объясняет поведение программы, так, в качестве локальной памяти не обязательно выступает кэш память, это могут быть регистры процессора или потоки могут вообще не иметь локальной памяти.
При входе в synchronized метод или блок поток обновляет содержимое локальной памяти, а при выходе из synchronized метода или блока поток записывает изменения, сделанные в локальной памяти, в главную. Такое поведение synchronized методов и блоков следует из правил для отношения «происходит раньше»: так как все операции с памятью происходят раньше освобождения монитора и освобождение монитора происходит раньше захвата монитора, то все операции с памятью, которые были сделаны потоком до выхода из synchronized блока должны быть видны любому потоку, который входит в synchronized блок для того же самого монитора. Очень важно, что это правило работает только в том случае, если потоки синхронизируются, используя один и тот же монитор!
Что касается volatile переменных, то запись таких переменных производится в основную память, минуя локальную. и чтение volatile переменной производится также из основной памяти, то есть значение переменной не может сохраняться в регистрах или локальной памяти потока и операция чтения этой переменной гарантированно вернёт последнее записанное в неё значение.
Есть одна проблема, связанная с final полями: реализация разрешает менять значения таких полей после создания объекта (это может быть сделано, например, с использованием механизма reflection). Если значение final поля—константа, чьё значение известно на момент компиляции, изменения такого поля могут не иметь эффекта, так-как обращения к этой переменной могли быть заменены компилятором на константу. Также спецификация разрешает другие оптимизации, связанные с final полями, например, операции чтения final переменной могут быть переупорядочены с операциями, которые потенциально могут изменить такую переменную. Так что рекомендуется изменять final поля объекта только внутри конструктора, в противном случае поведение не специфицировано.
Reordering (переупорядочивание). Для увеличения производительности процессор/компилятор могут переставлять местами некоторые инструкции/операции. Вернее, с точки зрения потока, наблюдающего за выполнением операций в другом потоке, операции могут быть выполнены не в том порядке, в котором они идут в исходном коде. Тот же эффект может наблюдаться, когда один поток кладет результаты первой операции в регистр или локальный кэш, а результат второй операции попадает непосредственно в основную память. Тогда второй поток, обращаясь к основной памяти может сначала увидеть результат второй операции, и только потом первой, когда все регистры или кэши синхронизируются с основной памятью. Еще одна причина reordering, может заключаться в том, что процессор может решить поменять порядок выполнения операций, если, например, сочтет что такая последовательность выполнится быстрее.
Вопрос reordering также регулируется набором правил для отношения «происходит раньше» и у этих правил есть следствие, касающееся порядка операций, используемое на практике: операции чтения и записи volatile переменных не могут быть переупорядочены с операциями чтения и записи других volatile и не- volatile переменных. Это следствие делает возможным использование volatile переменной как флага, сигнализирующем об окончании какого-либо действия. В остальном правила, касающиеся порядка выполнения операций, гарантируют упорядоченность операций для конкретного набора случаев (таких как, например, захват и освобождение монитора), во всех остальных случаях оставляя компилятору и процессору полную свободу для оптимизаций.
Что такое «потокобезопасность»?
Потокобезопасность – свойство объекта или кода, которое гарантирует, что при исполнении или использовании несколькими потоками, код будет вести себя, как предполагается. Например потокобезопасный счётчик не пропустит ни один счёт, даже если один и тот же экземпляр этого счётчика будет использоваться несколькими потоками.
В чём разница между «конкуренцией» и «параллелизмом»?
Конкуренция — это способ одновременного решения множества задач.
Параллелизм — это способ выполнения разных частей одной задачи.
Что такое «кооперативная многозадачность»? Какой тип многозадачности использует Java? Чем обусловлен этот выбор?
Java использует вытесняющую многозадачность, при которой решение о переключении между потоками процесса принимает операционная система.
В отличие от кооперативной многозадачности управление операционной системе передаётся вне зависимости от состояния работающих приложений, благодаря чему, отдельные зависшие потоки процесса, как правило, не «подвешивают» всю систему целиком. За счёт регулярного переключения между задачами также улучшается отзывчивость приложения и повышается оперативность освобождения ресурсов, которые больше не используются.
В реализации вытесняющая многозадачность отличается от кооперативной, в частности, тем, что требует обработки системного прерывания от аппаратного таймера.
Что такое ordering, as-if-serial semantics, sequential consistency, visibility, atomicity, happens-before, mutual exclusion, safe publication?
ordering механизм, который определяет, когда один поток может увидеть out-of-order (неверный) порядок исполнения инструкций другого потока. CPU для повышения производительности может переупорядочивать процессорные инструкции и выполнять их в произвольном порядке до тех пор пока для потока внутри не будет видно никаких отличий. Гарантия, предоставляемая этим механизмом, называется as-if-serial semantics.
visibility определяет, когда действия в одном потоке становятся видны из другого потока.
atomicity — атомарность операций. Атомарная операция выглядит единой и неделимой командой процессора, которая может быть или уже выполненной или ещё невыполненной.
Чем отличается процесс от потока?
Процесс — экземпляр программы во время выполнения, независимый объект, которому выделены системные ресурсы (например, процессорное время и память). Каждый процесс выполняется в отдельном адресном пространстве: один процесс не может получить доступ к переменным и структурам данных другого. Если процесс хочет получить доступ к чужим ресурсам, необходимо использовать межпроцессное взаимодействие. Это могут быть конвейеры, файлы, каналы связи между компьютерами и многое другое.
Для каждого процесса ОС создает так называемое «виртуальное адресное пространство», к которому процесс имеет прямой доступ. Это пространство принадлежит процессу, содержит только его данные и находится в полном его распоряжении. Операционная система же отвечает за то, как виртуальное пространство процесса проецируется на физическую память.
Поток(thread) — определенный способ выполнения процесса, определяющий последовательность исполнения кода в процессе. Потоки всегда создаются в контексте какого-либо процесса, и вся их жизнь проходит только в его границах. Потоки могут исполнять один и тот же код и манипулировать одними и теми же данными, а также совместно использовать описатели объектов ядра, поскольку таблица описателей создается не в отдельных потоках, а в процессах. Так как потоки расходуют существенно меньше ресурсов, чем процессы, в процессе выполнения работы выгоднее создавать дополнительные потоки и избегать создания новых процессов.
Что такое «зелёные потоки» и есть ли они в Java?
Виртуальная машина Java берёт на себя заботу о переключении между разными green threads, а сама машина работает как один поток ОС. Это даёт несколько преимуществ. Потоки ОС относительно дороги в большинстве POSIX-систем. Кроме того, переключение между native threads гораздо медленнее, чем между green threads.
Это всё означает, что в некоторых ситуациях green threads гораздо выгоднее, чем native threads. Система может поддерживать гораздо большее количество green threads, чем потоков OС. Например, гораздо практичнее запускать новый green thread для нового HTTP-соединения к веб-серверу, вместо создания нового native thread.
Однако есть и недостатки. Самый большой заключается в том, что вы не можете исполнять два потока одновременно. Поскольку существует только один native thread, только он и вызывается планировщиком ОС. Даже если у вас несколько процессоров и несколько green threads, только один процессор может вызывать green thread. И всё потому, что с точки зрения планировщика заданий ОС всё это выглядит одним потоком.
Начиная с версии 1.2 Java поддерживает native threads, и с тех пор они используются по умолчанию.
Каким образом можно создать поток?
Помимо того, что Runnable помогает разрешить проблему множественного наследования, несомненный плюс от его использования состоит в том, что он позволяет логически отделить логику выполнения задачи от непосредственного управления потоком.
Как принудительно запустить поток?
Никак. В Java не существует абсолютно никакого способа принудительного запуска потока. Это контролируется JVM и Java не предоставляет никакого API для управления этим процессом.
Что такое «монитор» в Java?
Монитор, мьютекс (mutex) – это средство обеспечения контроля за доступом к ресурсу. У монитора может быть максимум один владелец в каждый текущий момент времени. Следовательно, если кто-то использует ресурс и захватил монитор для обеспечения единоличного доступа, то другой, желающий использовать тот же ресурс, должен подождать освобождения монитора, захватить его и только потом начать использовать ресурс.
Удобно представлять монитор как id захватившего его объекта. Если этот id равен 0 – ресурс свободен. Если не 0 – ресурс занят. Можно встать в очередь и ждать его освобождения.
Дайте определение понятию «синхронизация».
В Java все объекты имеют одну блокировку, благодаря которой только один поток одновременно может получить доступ к критическому коду в объекте. Такая синхронизация помогает предотвратить повреждение состояния объекта. Если поток получил блокировку, ни один другой поток не может войти в синхронизированный код, пока блокировка не будет снята. Когда поток, владеющий блокировкой, выходит из синхронизированного кода, блокировка снимается. Теперь другой поток может получить блокировку объекта и выполнить синхронизированный код. Если поток пытается получить блокировку объекта, когда другой поток владеет блокировкой, поток переходит в состояние Блокировки до тех пор, пока блокировка не снимется.
Какие существуют способы синхронизации в Java?
В каких состояниях может находиться поток?
Потоки могут находиться в одном из следующих состояний:
Можно ли создавать новые экземпляры класса, пока выполняется static synchronized метод?
Да, можно создавать новые экземпляры класса, так как статические поля не принадлежат к экземплярам класса.
Зачем может быть нужен private мьютекс?
Эти методы определены у класса Object и предназначены для взаимодействия потоков между собой при межпоточной синхронизации.
Почему методы wait() и notify() вызываются только в синхронизированном блоке?
Чем отличается работа метода wait() с параметром и без параметра?
Метод yield() служит причиной того, что поток переходит из состояния работающий (running) в состояние работоспособный (runnable), давая возможность другим потокам активизироваться. Но следующий выбранный для запуска поток может и не быть другим.
Метод sleep() вызывает засыпание текущего потока на заданное время, состояние изменяется с работающий (running) на ожидающий (waiting).
Когда поток вызывает join() для другого потока, текущий работающий поток будет ждать, пока другой поток, к которому он присоединяется, не будет завершён:
Простейший способ избежать взаимной блокировки – не допускать цикличного ожидания. Этого можно достичь, получая мониторы разделяемых ресурсов в определённом порядке и освобождая их в обратном порядке.
livelock – тип взаимной блокировки, при котором несколько потоков выполняют бесполезную работу, попадая в зацикленность при попытке получения каких-либо ресурсов. При этом их состояния постоянно изменяются в зависимости друг от друга. Фактической ошибки не возникает, но КПД системы падает до 0. Часто возникает в результате попыток предотвращения deadlock.
Реальный пример livelock, – когда два человека встречаются в узком коридоре и каждый, пытаясь быть вежливым, отходит в сторону, и так они бесконечно двигаются из стороны в сторону, абсолютно не продвигаясь в нужном им направлении.
Как проверить, удерживает ли поток монитор определённого ресурса?
На каком объекте происходит синхронизация при вызове static synchronized метода?
В чём различия между volatile и Atomic переменными?
Что значит «приоритет потока»?
Приоритеты потоков используются планировщиком потоков для принятия решений о том, когда какому из потоков будет разрешено работать. Теоретически высокоприоритетные потоки получают больше времени процессора, чем низкоприоритетные. Практически объем времени процессора, который получает поток, часто зависит от нескольких факторов помимо его приоритета.
Можно ли сделать основной поток программы демоном?
Нет. Потоки-демоны позволяют описывать фоновые процессы, которые нужны только для обслуживания основных потоков выполнения и не могут существовать без них.
Что значит «усыпить» поток?
CountDownLatch (замок с обратным отсчетом) предоставляет возможность любому количеству потоков в блоке кода ожидать до тех пор, пока не завершится определенное количество операций, выполняющихся в других потоках, перед тем как они будут «отпущены», чтобы продолжить свою деятельность. В конструктор CountDownLatch(int count) обязательно передается количество операций, которое должно быть выполнено, чтобы замок «отпустил» заблокированные потоки.
Примером CountDownLatch из жизни может служить сбор экскурсионной группы: пока не наберется определенное количество человек, экскурсия не начнется.
CyclicBarrier реализует шаблон синхронизации «Барьер». Циклический барьер является точкой синхронизации, в которой указанное количество параллельных потоков встречается и блокируется. Как только все потоки прибыли, выполняется опционное действие (или не выполняется, если барьер был инициализирован без него), и, после того, как оно выполнено, барьер ломается и ожидающие потоки «освобождаются». В конструкторы барьера CyclicBarrier(int parties) и CyclicBarrier(int parties, Runnable barrierAction) обязательно передается количество сторон, которые должны «встретиться», и, опционально, действие, которое должно произойти, когда стороны встретились, но перед тем когда они будут «отпущены».
Что такое race condition?
Существует ли способ решения проблемы race condition?
Распространённые способы решения:
Очевидных способов выявления и исправления состояний гонки не существует. Лучший способ избавиться от гонок — правильное проектирование многозадачной системы.
Как остановить поток?
Схема действия при этом получается следующей:
Что происходит, когда в потоке выбрасывается исключение?
Механизм прерывания работы потока в Java реализован с использованием внутреннего флага, известного как статус прерывания. Прерывание потока вызовом Thread.interrupt() устанавливает этот флаг. Методы Thread.interrupted() и isInterrupted() позволяют проверить, является ли поток прерванным.
Нестатический метод isInterrupted() используется одним потоком для проверки статуса прерывания у другого потока, не изменяя флаг прерывания.
Что такое «пул потоков»?
Создание потока является затратной по времени и ресурсам операцией. Количество потоков, которое может быть запущено в рамках одного процесса также ограниченно. Чтобы избежать этих проблем и в целом управлять множеством потоков более эффективно в Java был реализован механизм пула потоков (thread pool), который создаётся во время запуска приложения и в дальнейшем потоки для обработки запросов берутся и переиспользуются уже из него. Таким образом, появляется возможность не терять потоки, сбалансировать приложение по количеству потоков и частоте их создания.
Методы Executors для создания пулов:
Какого размера должен быть пул потоков?
Настраивая размер пула потоков, важно избежать двух ошибок: слишком мало потоков (очередь на выполнение будет расти, потребляя много памяти) или слишком много потоков (замедление работы всей систему из-за частых переключений контекста).
Использование процессора – не единственный фактор, важный при настройке размера пула потоков. По мере возрастания пула потоков, можно столкнуться с ограничениями планировщика, доступной памяти, или других системных ресурсов, таких, как количество сокетов, дескрипторы открытого файла, или каналы связи базы данных.
Что будет, если очередь пула потоков уже заполнена, но подаётся новая задача?
В чём заключается различие между методами submit() и execute() у пула потоков?
Оба метода являются способами подачи задачи в пул потоков, но между ними есть небольшая разница.
execute(Runnable command) определён в интерфейсе Executor и выполняет поданную задачу и ничего не возвращает.
В чем заключаются различия между cтеком (stack) и кучей (heap) с точки зрения многопоточности?
Cтек – участок памяти, тесно связанный с потоками. У каждого потока есть свой стек, которые хранит локальные переменные, параметры методов и стек вызовов. Переменная, хранящаяся в стеке одного потока, не видна для другого.
Как поделиться данными между двумя потоками?
Какой параметр запуска JVM используется для контроля размера стека потока?
Как получить дамп потока?
Среды исполнения Java на основе HotSpot генерируют только дамп в формате HPROF. В распоряжении разработчика имеется несколько интерактивных методов генерации дампов и один метод генерации дампов на основе событий.
Метод на основе событий:
Что такое ThreadLocal-переменная?
Следует обратить внимание, что ThreadLocal изолирует именно ссылки на объекты, а не сами объекты. Если изолированные внутри потоков ссылки ведут на один и тот же объект, то возможны коллизии.
Что понимается под блокировкой с повторным входом (reentrant)? Просто то, что есть подсчет сбора данных, связанный с блокировкой, и если поток, который удерживает блокировку, снова ее получает, данные отражают увеличение, и тогда для реального разблокирования нужно два раза снять блокировку. Это аналогично семантике synchronized; если поток входит в синхронный блок, защищенный монитором, который уже принадлежит потоку, потоку будет разрешено дальнейшее функционирование, и блокировка не будет снята, когда поток выйдет из второго (или последующего) блока synchronized, она будет снята только когда он выйдет из первого блока synchronized, в который он вошел под защитой монитора.
Резюмируя, можно сказать, что когда состязания за блокировку нет либо оно очень мало, то synchronized возможно будет быстрее. Если присутствует заметное состязание за доступ к ресурсу, то скорее всего ReentrantLock даст некое преимущество.
Что такое «блокирующий метод»?
Блокирующий метод – метод, который блокируется, до тех пор, пока задание не выполнится, например метод accept() у ServerSocket блокируется в ожидании подключения клиента. Здесь блокирование означает, что контроль не вернётся к вызывающему методу до тех пор, пока не выполнится задание. Так же существуют асинхронные или неблокирующиеся методы, которые могут завершится до выполнения задачи.
Что такое «фреймворк Fork/Join»?
Решение всех подзадач (в т.ч. и само разбиение на подзадачи) происходит параллельно.
Для решения некоторых задач этап Join не требуется. Например, для параллельного QuickSort — массив рекурсивно делится на всё меньшие и меньшие диапазоны, пока не вырождается в тривиальный случай из 1 элемента. Хотя в некотором смысле Join будет необходим и тут, т.к. всё равно остаётся необходимость дождаться пока не закончится выполнение всех подзадач.
Ещё одно замечательное преимущество этого фреймворка заключается в том, что он использует work-stealing алгоритм: потоки, которые завершили выполнение собственных подзадач, могут «украсть» подзадачи у других потоков, которые всё ещё заняты.
Semaphore – это новый тип синхронизатора: семафор со счётчиком, реализующий шаблон синхронизации Семафор. Доступ управляется с помощью счётчика: изначальное значение счётчика задаётся в конструкторе при создании синхронизатора, когда поток заходит в заданный блок кода, то значение счётчика уменьшается на единицу, когда поток его покидает, то увеличивается. Если значение счётчика равно нулю, то текущий поток блокируется, пока кто-нибудь не выйдет из защищаемого блока. Semaphore используется для защиты дорогих ресурсов, которые доступны в ограниченном количестве, например подключение к базе данных в пуле.
Что такое double checked locking Singleton?
Следует заметить, что требование volatile обязательно. Проблема Double Checked Lock заключается в модели памяти Java, точнее в порядке создания объектов, когда возможна ситуация, при которой другой поток может получить и начать использовать (на основании условия, что указатель не нулевой) не полностью сконструированный объект. Хотя эта проблема была частично решена в JDK 1.5, однако рекомендация использовать volatile для Double Cheсked Lock остаётся в силе.
Как создать потокобезопасный Singleton?
Чем полезны неизменяемые объекты?
Что такое busy spin?
Перечислите принципы, которым вы следуете в многопоточном программировании?
При написании многопоточных программ следует придерживаться определённых правил, которые помогают обеспечить достойную производительность приложения в сочетании с удобной отладкой и простотой дальнейшей поддержки кода.
Какое из следующих утверждений о потоках неверно?
Вызов метода start() дважды для одного и того же объекта Thread приведёт к генерированию исключения IllegalThreadStateException во время выполнения, следовательно, утверждение 1 верно. Утверждение 2 верно, так как порядок, в котором выполняются потоки, определяется Планировщиком потоков, независимо от того, какой поток запущен первым. Утверждение 4 верно, так как поток не освободит блокировки, которые он держит, когда он переходит в состояние Ожидания.
Даны 3 потока Т1, Т2 и Т3? Как реализовать выполнение в последовательности Т1, Т2, Т3?
Напишите минимальный неблокирующий стек (всего два метода — push() и pop() ).