что такое поток демон java

Введение в многопоточность

Содержание

Есть два способа создания потоков в Java: унаследоваться от класса Thread или реализовать интерфейс Runnable.

Создание потока через наследование

Рассмотрим пример, в котором мы расширяем стандартный класс Thread, переопределяя лишь один метод run(). В нём мы ждём 3 секунды, а затем выводим сообщение о завершении потока. Обратите внимание, что запуск потока осуществляется не через метод run(), а через метод start().

public class ThinkerThread extends Thread <

public static void main(String[] args) <
new ThinkerThread().start();
System.out.println( «Основной поток завершён» );
>
>

Метод TimeUnit.SECONDS.sleep() полностью эквивалентен стандартному Thread.sleep(), однако в первом случае мы явно указываем единицы измерения времени, что делает код более читаемым. Я рекомендую использовать именно такую форму записи.

Поскольку метод sleep() относится к низкоуровневым, он может кидать InterruptedException, которое свидетельствует о том, что поток был прерван. Это исключение является единственным признаком того, что поток был принудительно остановлен. И чтобы не терять эту информацию в стеке вызовов, мы выставляем флаг interrupted при помощи соответствующего метода Thread.currentThread(). Такой способ обработки InterruptedException является правильным и именно его нужно использовать в подобных случаях.

В результате запуска второго потока мы сначала увидим сообщение о том, что основной поток завершён, а затем будем дожидаться завершения второго потока.

Создание потока через интерфейс

Теперь создадим поток с помощью интерфейса Runnable.

public class ThinkerRunnable implements Runnable <

public static void main(String[] args) <
new Thread( new ThinkerRunnable()).start();
System.out.println( «Основной поток завершён» );
>
>

Интерфейс Runnable требует определить единственный метод run(). Для запуска потока требуется создать объект Thread, передав ему в конструктор экземпляр нашего класса. Затем у этого объекта Thread вызываем метод start(). Данный вариант является более предпочтительным, если наш класс уже наследуется от какого-то другого базового класса.

Потоки-демоны

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

public class DaemonThread extends Thread <

public static void main(String[] args) <
Thread thread = new DaemonThread();
thread.setDaemon( true );
thread.start();
System.out.println( «Основной поток завершён» );
>
>

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

Как остановить поток

Остановить поток можно с помощью метода interrupt(). В случае, если поток не является демоном, то возникает исключение InterruptedException, о котором мы говорили выше.

public class ThinkerThread extends Thread <

public static void main(String[] args) <
Thread thread = new ThinkerThread();
thread.start();
System.out.println( «Основной поток завершён» );
thread.interrupt();
>
>

Но вызов interrupt() следует толковать не как принудительную остановку, а как вежливый запрос. Немного изменим пример, чтобы показать, как должна обрабатываться остановка. Для имитации тяжёлой задачи сделаем цикл в котором будем вычислять тригонометрическую функцию.

public class ThinkerThread extends Thread <

Источник

Что такое поток демона в Java?

Может ли кто-нибудь сказать мне, какие потоки демона находятся в Java?

25 ответов

Вы можете использовать метод setDaemon(boolean) для изменения свойств демона Thread до начала потока.

Когда все потоки, не являющиеся демонами, заканчивают работу, JVM останавливается, а все оставшиеся потоки демонов удаляются:

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

Традиционно процессы демона в UNIX были теми, которые постоянно работали в фоновом режиме, подобно сервисам в Windows.

Темы Daemon похожи на поставщиков услуг для других потоков или объектов, работающих в том же процессе, что и поток демона. Потоки Daemon используются для поддержки фоновых задач и необходимы только при выполнении обычных потоков. Если нормальные потоки не выполняются, а оставшиеся потоки являются потоками демона, то интерпретатор завершает работу.

Например, браузер HotJava использует до четырех потоков демона с именем «Image Fetcher» для извлечения изображений из файловой системы или сети для любого потока, который нуждается в нем.

Темы демона обычно используются для выполнения сервисов для вашего приложения/апплета (например, загрузки «фиктивных бит» ). Основное различие между потоками пользователей и потоками демона заключается в том, что JVM будет только закрывать программу, когда все пользовательские потоки прекратятся. Потоки Daemon прерываются JVM, когда больше нет пользовательских потоков, включая основной поток выполнения.

setDaemon (true/false)? Этот метод используется для указания, что поток является потоком демона.

Когда ваша программа будет иметь только оставшиеся демонные потоки, она выйдет. Это потому, что обычно эти потоки работают вместе с обычными потоками и обеспечивают фоновую обработку событий.

Определение демона (вычислительного):

Фоновый процесс, который обрабатывает запросы на такие службы, как спулинг печати и передача файлов, и не используется, когда не требуется.

Что такое поток демонов в Java?

Одно заблуждение, которое я хотел бы уточнить:

Источник

Что такое поток демона в Java?

Кто-нибудь может сказать мне, что потоки демона в Java?

Когда все потоки, не являющиеся демонами, заканчивают работу, JVM останавливается, а все оставшиеся потоки демонов удаляются :

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

Традиционно демон-процессы в UNIX были такими, которые постоянно работали в фоновом режиме, во многом как сервисы в Windows.

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

Например, браузер HotJava использует до четырех потоков демонов с именем «Сборщик изображений» для извлечения изображений из файловой системы или сети для любого потока, который в этом нуждается.

Потоки демона обычно используются для выполнения сервисов для вашего приложения/апплета (например, загрузка «битов фиддли»). Основное различие между пользовательскими потоками и потоками демонов состоит в том, что JVM закроет программу только после завершения всех пользовательских потоков. Потоки демона завершаются JVM, когда пользовательские потоки больше не работают, включая основной поток выполнения.

setDaemon (true/false)? Этот метод используется для указания того, что поток является потоком демона.

public boolean isDaemon ()? Этот метод используется для определения того, является ли поток потоком демона или нет.

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

Определение демона (вычислений):

Фоновый процесс, который обрабатывает запросы на такие службы, как спулинг печати и передача файлов, и бездействует, когда не требуется.

Что такое поток демонов в Java?

Одно заблуждение я хотел бы уточнить:

Демоническая и пользовательская темы. Обычно все потоки, созданные программистом, являются пользовательскими (если вы не укажете, что это демон, или ваш родительский поток не является потоком демона). Пользовательский поток обычно предназначен для запуска нашего программного кода. JVM не завершается, если не завершен весь поток пользователя.

В Java есть специальный вид потока, называемый daemon thread.

Для чего используются потоки демонов?

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

Нити демонов похожи на помощников. Non-Daemon темы как фронт-исполнители. Помощники помогают исполнителям завершить работу. Когда работа завершена, исполнители больше не нуждаются в помощи. Поскольку помощь не требуется, помощники покидают это место. Поэтому, когда задания потоков, не являющихся демонами, заканчиваются, потоки демонов удаляются.

Поток демона аналогичен обычному потоку, за исключением того, что JVM отключается только тогда, когда другие потоки, не являющиеся демонами, не существуют. Потоки демонов, как правило, используются для предоставления сервисов для вашего приложения.

указывает на примечание:

Любой поток, созданный основным потоком, который запускает основной метод в Java, по умолчанию не является демоном, поскольку поток наследует свою природу демона из потока, который создает его, т.е. родительский поток, а поскольку основной поток является потоком, не являющимся демоном, любой другой поток, созданный из него, останется не демоном до тех пор, пока он не станет явно демоном, вызвав setDaemon (true).

Thread.setDaemon (true) создает демон Thread, но его можно вызвать только перед запуском Thread в Java. Он выдаст исключение IllegalThreadStateException, если соответствующий поток уже запущен и работает.

Разница между потоками Daemon и Non Daemon в Java:

1) JVM не ожидает завершения работы какого-либо потока демона перед его созданием.

2) Поток демона обрабатывается иначе, чем пользовательский поток, когда JVM завершается, наконец, блоки не вызываются, стеки не разматываются, а JVM просто выходит.

Потоки демонов обычно называются потоками «Service Provider». Эти потоки должны использоваться не для выполнения программного кода, а для системного кода. Эти потоки работают параллельно вашему коду, но JVM может уничтожить их в любое время. Когда JVM не находит пользовательских потоков, он останавливает его, и все потоки демона мгновенно завершаются. Мы можем установить поток, не являющийся демоном, в демон, используя:

При установке thread.setDaemon(true) поток становится потоком демона. Однако вы можете установить это значение только до начала потока.

Потоки демонов, как все объяснили, не будут ограничивать выход из JVM, так что в основном это счастливый поток для Application с точки зрения выхода.

Хочу добавить, что потоки демона можно использовать, когда, скажем, я предоставляю такой API-интерфейс, как отправка данных на сторонний сервер или JMS, может потребоваться агрегировать данные на уровне клиентской JVM и затем отправлять их в JMS в отдельном потоке. Я могу сделать этот поток потоком демона, если это не обязательные данные для отправки на сервер. Этот вид данных похож на журнал регистрации/агрегирования.

Для дополнительной справки: Поток демона в Java

Поговорим только в коде с рабочими примерами. Мне нравится ответ Русса выше, но чтобы убрать любые сомнения, я немного их улучшил. Я запускал его дважды, один раз с рабочим потоком, установленным в deamon true (поток deamon), а в другой раз установил его в false (пользовательский поток). Это подтверждает, что поток deamon заканчивается, когда заканчивается основной поток.

Вот пример для тестирования поведения потоков демона в случае выхода из jvm из-за отсутствия пользовательских потоков.

Обратите внимание на вторую последнюю строку в выходных данных ниже, когда основной поток вышел, поток демона также умер и не печатал оператор окончательно выполненный9 в блоке finally. Это означает, что любые ресурсы ввода-вывода, закрытые в блоке finally потока демона, не будут закрыты, если JVM завершит работу из-за отсутствия пользовательских потоков.

Результат

Нити демона умирают при выходе из нити создателя.

Потоки, не являющиеся демонами (по умолчанию), могут даже жить дольше, чем основной поток.

Источник

Что такое поток демона в Java?

Вы можете использовать setDaemon(boolean) метод для изменения Thread свойств демона до запуска потока.

Когда все потоки, не являющиеся демонами, заканчивают работу, JVM останавливается, а все оставшиеся потоки демонов удаляются :

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

Традиционно демон-процессы в UNIX были такими, которые постоянно работали в фоновом режиме, во многом как сервисы в Windows.

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

Например, браузер HotJava использует до четырех потоков демонов с именем «Сборщик изображений» для извлечения изображений из файловой системы или сети для любого потока, который в этом нуждается.

Потоки демона обычно используются для выполнения сервисов для вашего приложения / апплета (например, загрузка «битов фиддли»). Основное различие между пользовательскими потоками и потоками демонов состоит в том, что JVM закроет программу только после завершения всех пользовательских потоков. Потоки демона завершаются JVM, когда пользовательские потоки больше не работают, включая основной поток выполнения.

setDaemon (true / false)? Этот метод используется, чтобы указать, что поток является потоком демона.

public boolean isDaemon ()? Этот метод используется для определения того, является ли поток потоком демона или нет.

Определение демона (вычислений):

Фоновый процесс, который обрабатывает запросы на такие службы, как спулинг печати и передача файлов, и бездействует, когда не требуется.

Что такое поток демонов в Java?

Когда в вашей программе остались только потоки демонов, она завершится. Это потому, что обычно эти потоки работают вместе с обычными потоками и обеспечивают фоновую обработку событий.

Одно заблуждение я хотел бы уточнить:

Демоническая и пользовательская темы. Обычно все потоки, созданные программистом, являются пользовательскими (если вы не укажете, что это демон, или ваш родительский поток не является потоком демона). Пользовательский поток обычно предназначен для запуска нашего программного кода. JVM не завершается, если не завершен весь поток пользователя.

Для чего используются потоки демонов?

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

Источник

Многопоточность Thread, Runnable

Многопоточное программирование позволяет разделить представление и обработку информации на несколько «легковесных» процессов (light-weight processes), имеющих общий доступ как к методам различных объектов приложения, так и к их полям. Многопоточность незаменима в тех случаях, когда графический интерфейс должен реагировать на действия пользователя при выполнении определенной обработки информации. Потоки могут взаимодействовать друг с другом через основной «родительский» поток, из которого они стартованы.

В качестве примера можно привести некоторый поток, отвечающий за представление информации в интерфейсе, который ожидает завершения работы другого потока, загружающего файл, и одновременно отображает некоторую анимацию или обновляет прогресс-бар. Кроме того этот поток может остановить загружающий файл поток при нажатии кнопки «Отмена».

Преимущества потоков перед процессами

Главный поток

Каждое java приложение имеет хотя бы один выполняющийся поток. Поток, с которого начинается выполнение программы, называется главным. После создания процесса, как правило, JVM начинает выполнение главного потока с метода main(). Затем, по мере необходимости, могут быть запущены дополнительные потоки. Многопоточность — это два и более потоков, выполняющихся одновременно в одной программе. Компьютер с одноядерным процессором может выполнять только один поток, разделяя процессорное время между различными процессами и потоками.

Класс Thread

В классе Thread определены семь перегруженных конструкторов, большое количество методов, предназначенных для работы с потоками, и три константы (приоритеты выполнения потока).

Конструкторы класса Thread

Пример создания потока, который входит в группу, реализует интерфейс Runnable и имеет свое уникальное название :

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

Несмотря на то, что главный поток создаётся автоматически, им можно управлять. Для этого необходимо создать объект класса Thread вызовом метода currentThread().

Методы класса Thread

Наиболее часто используемые методы класса Thread для управления потоками :

Жизненный цикл потока

При выполнении программы объект Thread может находиться в одном из четырех основных состояний: «новый», «работоспособный», «неработоспособный» и «пассивный». При создании потока он получает состояние «новый» (NEW) и не выполняется. Для перевода потока из состояния «новый» в «работоспособный» (RUNNABLE) следует выполнить метод start(), вызывающий метод run().

Поток может находиться в одном из состояний, соответствующих элементам статически вложенного перечисления Thread.State :

NEW — поток создан, но еще не запущен;
RUNNABLE — поток выполняется;
BLOCKED — поток блокирован;
WAITING — поток ждет окончания работы другого потока;
TIMED_WAITING — поток некоторое время ждет окончания другого потока;
TERMINATED — поток завершен.

Пример использования Thread

В примере ChickenEgg рассматривается параллельная работа двух потоков (главный поток и поток Egg), в которых идет спор, «что было раньше, яйцо или курица?». Каждый поток высказывает свое мнение после небольшой задержки, формируемой методом ChickenEgg.getTimeSleep(). Побеждает тот поток, который последним говорит свое слово.

При выполнении программы в консоль было выведено следующее сообщение.

Невозможно точно предсказать, какой поток закончит высказываться последним. При следующем запуске «победитель» может измениться. Это происходит вследствии так называемого «асинхронного выполнения кода». Асинхронность обеспечивает независимость выполнения потоков. Или, другими словами, параллельные потоки независимы друг от друга, за исключением случаев, когда бизнес-логика зависимости выполнения потоков определяется предусмотренными для этого средств языка.

Интерфейс Runnable

Интерфейс Runnable содержит только один метод run() :

Метод run() выполняется при запуске потока. После определения объекта Runnable он передается в один из конструкторов класса Thread.

Пример класса RunnableExample, реализующего интерфейс Runnable

При выполнении программы в консоль было выведено следующее сообщение.

Синхронизация потоков, synchronized

В процессе функционирования потоки часто используют общие ресурсы приложения, определенные вне потока. Если несколько потоков начнут одновременно вносить изменения в общий ресурс, то результаты выполнения программы могут быть непредсказуемыми. Рассмотрим следующий пример :

В примере определен общий ресурс в виде класса CommonObject, в котором имеется целочисленное поле counter. Данный ресурс используется внутренним классом, создающим поток CounterThread для увеличения в цикле значения counter на единицу. При старте потока полю counter присваивается значение 1. После завершения работы потока значение res.counter должно быть равно 4.

Две строчки кода класса CounterThread закомментированы. О них речь пойдет ниже.

В главном классе программы SynchronizedThread.main запускается пять потоков. То есть, каждый поток должен в цикле увеличить значение res.counter с единицы до четырех; и так пять раз. Но результат работы программы, отображаемый в консоли, будет иным :

То есть, с общим ресурсов res.counter работают все потоки одновременно, поочередно изменяя значение.

Чтобы избежать подобной ситуации, потоки необходимо синхронизировать. Одним из способов синхронизации потоков связан с использованием ключевого слова synchronized. Оператор synchronized позволяет определить блок кода или метод, который должен быть доступен только одному потоку. Можно использовать synchronized в своих классах определяя синхронизированные методы или блоки. Но нельзя использовать synchronized в переменных или атрибутах в определении класса.

Блокировка на уровне объекта

Блокировать общий ресурс можно на уровне объекта, но нельзя использовать для этих целей примитивные типы. В примере следует удалить строчные комментарии в классе CounterThread, после чего общий ресурс будет блокироваться как только его захватит один из потоков; остальные потоки будут ждать в очереди освобождения ресурса. Результат работы программы при синхронизации доступа к общему ресурсу резко изменится :

Следующий код демонстрирует порядок использования оператора synchronized для блокирования доступа к объекту.

Блокировка на уровне метода и класса

Блокировать доступ к ресурсам можно на уровне метода и класса. Следующий код показывает, что если во время выполнения программы имеется несколько экземпляров класса DemoClass, то только один поток может выполнить метод demoMethod(), для других потоков доступ к методу будет заблокирован. Это необходимо когда требуется сделать определенные ресурсы потокобезопасными.

Каждый объект в Java имеет ассоциированный с ним монитор, который представляет своего рода инструмент для управления доступа к объекту. Когда выполнение кода доходит до оператора synchronized, монитор объекта блокируется, предоставляя монопольный доступ к блоку кода только одному потоку, который произвел блокировку. После окончания работы блока кода, монитор объекта освобождается и он становится доступным для других потоков.

Некоторые важные замечания использования synchronized

Примечание : для синхронизации потоков можно использовать объекты синхронизации Synchroniser’s пакета java.util.concurrent.

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

С использованием блокировок необходимо быть очень внимательным, чтобы не создать «взаимоблокировку», которая хорошо известна разработчикам. Этот термин означает, что один из потоков ждет от другого освобождения заблокированного им ресурса, в то время как сам также заблокировал один из ресурсов, доступа к которому ждёт второй поток. В данном процессе могут участвовать два и более потоков.

Основные условия возникновения взаимоблокировок в многопотоковом приложении :

Взаимодействие между потоками в Java, wait и notify

При взаимодействии потоков часто возникает необходимость приостановки одних потоков и их последующего извещения о завершении определенных действий в других потоков. Так например, действия первого потока зависят от результата действий второго потока, и надо каким-то образом известить первый поток, что второй поток произвел/завершил определенную работу. Для подобных ситуаций используются методы :

Все эти методы вызываются только из синхронизированного контекста (синхронизированного блока или метода).

Рассмотрим пример «Производитель-Склад-Потребитель» (Producer-Store-Consumer). Пока производитель не поставит на склад продукт, потребитель не может его забрать. Допустим производитель должен поставить 5 единиц определенного товара. Соответственно потребитель должен весь товар получить. Но, при этом, одновременно на складе может находиться не более 3 единиц товара. При реализации данного примера используем методы wait() и notify().

Листинг класса Store

Класс Store содержит два синхронизированных метода для получения товара get() и для добавления товара put(). При получении товара выполняется проверка счетчика counter. Если на складе товара нет, то есть counter

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *