Life Cycle of a Thread in Java
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
We rely on other people’s code in our own work. Every day.
It might be the language you’re writing in, the framework you’re building on, or some esoteric piece of software that does one thing so well you never found the need to implement it yourself.
The problem is, of course, when things fall apart in production — debugging the implementation of a 3rd party library you have no intimate knowledge of is, to say the least, tricky.
Lightrun is a new kind of debugger.
It’s one geared specifically towards real-life production environments. Using Lightrun, you can drill down into running applications, including 3rd party dependencies, with real-time logs, snapshots, and metrics.
Learn more in this quick, 5-minute Lightrun tutorial:
Slow MySQL query performance is all too common. Of course it is. A good way to go is, naturally, a dedicated profiler that actually understands the ins and outs of MySQL.
The Jet Profiler was built for MySQL only, so it can do things like real-time query performance, focus on most used tables or most frequent queries, quickly identify performance issues and basically help you optimize your queries.
Critically, it has very minimal impact on your server’s performance, with most of the profiling work done separately — so it needs no server changes, agents or separate services.
Basically, you install the desktop application, connect to your MySQL server, hit the record button, and you’ll have results within minutes:
DbSchema is a super-flexible database designer, which can take you from designing the DB with your team all the way to safely deploying the schema.
The way it does all of that is by using a design model, a database-independent image of the schema, which can be shared in a team using GIT and compared or deployed on to any database.
And, of course, it can be heavily visual, allowing you to interact with the database using diagrams, visually compose queries, explore the data, generate random data, import data or build HTML5 database reports.
The Kubernetes ecosystem is huge and quite complex, so it’s easy to forget about costs when trying out all of the exciting tools.
To avoid overspending on your Kubernetes cluster, definitely have a look at the free K8s cost monitoring tool from the automation platform CAST AI. You can view your costs in real time, allocate them, calculate burn rates for projects, spot anomalies or spikes, and get insightful reports you can share with your team.
Connect your cluster and start monitoring your K8s costs right away:
Жизненный цикл thread java
New — состояние, когда поток создан и готов к использованию. Это состояние, когда мы еще не запустили поток.
Running — состояние, в которое поток переходит после того, как мы его запустили. В этом состоянии поток выполняет свою работу, т. е. логику, которую мы определили.
Waiting — состояние ожидания, в которое поток может перейти во время своего выполнения. Есть три состояний ожидания — Blocked , Waiting , TimedWaiting . Например, когда поток пытается получить монитор объекта, он входит в состояние блокировки — Blocked ; когда поток ожидает выполнения другого потока, тогда поток переходит в состояние ожидания — Waiting , а когда поток ожидает только определённое количество времени для выполнения другого потока, поток входит в состояние — TimedWaiting . Поток возвращается в состояние — Running , как только другие потоки выполнили или освободили монитор объекта. Поток может бесконечно менять свое состояние из состояния — Running в состояние — Waiting и наоборот.
Dead / Terminated — состояние, в которое поток переходит после завершения выполнения или в случае возникновения исключений. Поток после выполнения не может быть запущен снова. Если мы попытаемся запустить поток в состоянии — Dead / Terminated , мы получим исключение IllegalStateException .
Thread join()
Еще один полезный метод, предоставляемый классом Thread — join() . При написании многопоточных программ могут быть случаи, когда необходимо ждать завершения выполнения какого-либо потока и после этого продолжить выполнение текущего потока. В таких случаях полезно применять метод — join() . Данный метод позволяет одному потоку ожидать завершения другого.
Рассмотрим следующий пример:
Как только threadTwo начинает выполняться, метод main() продолжает свое выполнение, он печатает — «Main method executing» и завершает свое выполнение. Параллельно выполняется threadTwo , считает до 1000, потом выводит — «Counter has finished its execution, counter = 1000» и заканчивает выполнение.
Но что, если мы хотим, чтобы основной поток ждал завершения выполнения потока — threadTwo ? Как этого добиться? Довольно просто — использование join() делает то, что нужно.
Рассмотрим следующий пример:
Порядок вывода в этом примере изменился. Сразу после запуска threadTwo , основной поток вызывает метод join() у потока — threadTwo . Это приводит к тому, что основной поток переходит в состояние ожидания и ждет, пока threadTwo не завершит свое выполнение. Как видно из вывода, поток — threadTwo завершает выполнение, считает до 1000 и выводит сообщение — «Counter has finished its execution, counter = 1000» и заканчивает выполнение. После этого mainThread продолжает свое выполнение и выводит следующее сообщение — «Main method executing».
Вдобавок, если во время выполнения потока — threadTwo возникнет исключение, основной поток продолжит свое выполнение аналогично как в случае с успешным выполнением потока — threadTwo , ситуаций deadlock не будет.
🧩☕ Интересные задачи по Java для практики можно найти на нашем телеграм-канале «Библиотека задач по Java»
Daemon Threads
В Java существует два типа потоков — пользовательские (те, которые мы создаем) потоки и потоки-демоны . Когда запускается Java-программа, сразу же начинается выполняться один поток — основной поток. Основной поток запускает метод main() . Мы можем создавать новые потоки из основного потока. Основной поток завершает выполнение последним, поскольку он выполняет различные операции завершения работы c потоками ввода и вывода, отключает соединения с базами данных и т. д.
Потоки-демоны в основном функционируют как вспомогательные потоки, они выполняют разные операции в фоновом режиме. Например, Garbage Collection в Java выполняется в фоновом режиме как поток-демон .
В основном потоке мы можем создавать столько потоков, сколько необходимо. Более того, класс Thread предоставляет метод setDaemon(boolean) , который позволяет рабочему (=пользовательскому) потоку превратиться в поток-демон.
- поток с низким приоритетом, работающий в фоновом режиме;
- поток-демон автоматически завершается виртуальной машиной Java, когда все остальные рабочие (worker threads) потоки завершают выполнение;
- обычно потоки-демоны используются для операций ввода-вывода и сервисов (в смартфонах для связи Bluetooth или NFC).
Основное различие между пользовательским потоком и потоком-демон заключается в том, что когда все рабочие (=основные или пользовательские) потоки завершают выполнение или умирают, потоки-демоны автоматически завершаются JVM, даже если они все еще выполняются.
Thread.getName()
Давайте определим наш собственный поток-демон. Мы создадим поток-демон, который будет печатать сообщение каждую секунду.
Кроме того, setDaemon(boolean) можно вызывать только в том случае, если поток находится в состоянии New и пока ещё не запущен, иначе мы получим исключение IllegalThreadStateException .
В этой части статей о многопоточности мы обсудили жизненный цикл потока, метод Thread.join() и потоки-демоны. В следующей статье обсудим синхронизацию потоков, что такое монитор объекта и взаимодействие между потоками.
Материалы по теме
Жизненный цикл потока в Java
В этой статье мы подробно обсудим основную концепцию Java — жизненный цикл потока.
Мы будем использовать краткую иллюстрированную диаграмму и, конечно же, практические фрагменты кода, чтобы лучше понять эти состояния во время выполнения потока.
Чтобы начать понимать потоки в Java, эта статья о создании потока является хорошей отправной точкой.
2. Многопоточность в Java
В языке Java многопоточность управляется основной концепцией Thread . В течение своего жизненного цикла потоки проходят через различные состояния:
3. Жизненный цикл потока в Java
Класс java.lang.Thread содержит статическое перечисление состояний , которое определяет его потенциальные состояния. В любой момент времени поток может находиться только в одном из следующих состояний:
- NEW — вновь созданный поток, который еще не начал выполнение
- RUNNABLE — либо запущен, либо готов к выполнению, но ожидает выделения ресурсов
- ЗАБЛОКИРОВАНО — ожидание получения блокировки монитора для входа или повторного входа в синхронизированный блок/метод
- WAITING — ожидание выполнения какого-либо другого потока определенного действия без ограничения времени.
- TIMED_WAITING — ожидание того, что какой-то другой поток выполнит определенное действие в течение указанного периода.
- TERMINATED – завершил выполнение
Все эти состояния показаны на диаграмме выше; давайте теперь обсудим каждый из них подробно.
3.1. Новый
НОВАЯ нить (или рожденная нить ) — это нить, которая была создана, но еще не запущена. Он остается в этом состоянии до тех пор, пока мы не запустим его с помощью метода start() .
В следующем фрагменте кода показан только что созданный поток, находящийся в состоянии NEW :
Runnable runnable = new NewState(); Thread t = new Thread(runnable); Log.info(t.getState());
Поскольку мы не запустили указанный поток, метод t.getState() выводит: