Легко ли таким образом понять жизненный цикл потока?

Java
Легко ли таким образом понять жизненный цикл потока?

| Красиво, пожалуйста, лайкните, выработайте привычку

  • У тебя одна мысль, у меня одна мысль, после того как мы обменяемся, у одного человека две мысли

  • If you can NOT explain it simply, you do NOT understand it well enough

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

Зачем понимать жизненный цикл потока?

Я уже писал трилогию о жизненном цикле Spring Bean:

  1. Происхождение жизненного цикла Spring Bean
  2. Конец жизненного цикла Spring Bean
  3. Что такое Spring Aware?

Друг оставил сообщение и сказал: «После понимания их жизненного цикла использование Spring Bean похоже на наблюдение за их траекторией, и теперь я совсем не паникую». Как и у него, цель понимания жизненного цикла вещей очень проста, только [без паники] также

Серия параллелизма JavaЯ много писал, но никогда не упоминал об этом [жизненный цикл потока Java]. С предзнаменованием графики теории предварительного заказа, прежде чем войти в мир исходного кода, самое время поговорить об этом. Потому что одним из основных принципов написания параллельных программ является правильная работа с состоянием потока.

Несколько состояний жизненного цикла потока

Когда я впервые столкнулся с жизненным циклом потоков, я всегда не мог вспомнить или понять их состояния, что, можно сказать, сбивало с толку, не говоря уже о переходах состояний между ними. Причина в том, что я поставил操作系统通用线程状态а также编程语言封装后的线程状态Понятия перепутаны

Общее состояние потока операционной системы

Лично я думаю, что общее состояние потока больше соответствует нашим привычкам мышления. Всего существует 5 состояний (как показано ниже). Студенты, которые часто пишут параллельные программы, часто читают эти общие состояния потоков в операционной системе и видят

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

Для лучшего объяснения通用线程状态а такжеJava 语言中的线程状态, вот краткое описание бывшего

начальное состояние

Поток создан, но ему еще не разрешено выделять ЦП для выполнения.Обратите внимание, что на самом деле это создается на уровне языка программирования, а в операционной системе настоящий поток еще не создан., например new Thread() в языке Java.

рабочее состояние

Потоки могут выделять ЦП для выполнения,На данный момент поток успешно создан в операционной системе.

Рабочий статус

Операционная система будет处在可运行状态的线程Выделите кванты времени процессора.После того, как ЦП повезет, поток в рабочем состоянии станет рабочим состоянием

состояние сна

Если работающий поток вызывает某个阻塞的APIили等待某个事件条件可用, то поток перейдет в спящее состояние,Примечание: В это время поток освобождает право на использование ЦП. Спящий поток никогда не будет иметь возможности получить право на использование ЦП. Только когда произойдет событие ожидания, поток перейдет из состояния сна в состояние ожидания. работоспособное состояние.

состояние окончания

线程执行完или出现异常(Это не считается прерванным, я расскажу об этом позже) Он войдет в состояние завершения, официально достигнув конца жизни, и шансов вернуться к жизни нет.

Далее давайте взглянем на жизненный цикл потока Java, с которым вы знакомы и не знакомы и который часто задают на собеседованиях.

Состояние потока языка Java

В исходном коде Thread определен класс-перечисление State, который четко записывает шесть состояний потоков на языке Java:

  1. NEW
  2. RUNNABLE
  3. BLOCKED
  4. WAITING
  5. TIMED_WAITING
  6. TERMINATED

Небольшое расследование, вы смотрели класс и читали его аннотации? (Добро пожаловать, чтобы оставить сообщение для следов)

В ушах звенела песня пяти звонков, а состояние потока в Java оказалось на 1 больше, чем 5 типов общих состояний потока, и стало 6 типов. Это кажется сложным, но это не то, что вы думаете.Исходя из общего состояния потока, Java имеет адаптацию и богатство.В целом, одним меньше. Посмотрите на картинку еще раз, обратите внимание на различие цветов

на языке Java

  • общее состояние потока可运行状态а также运行状态слился вRunnable,
  • будет休眠状态делится на три (BLOCKED/WAITING/TIMED_WAITING); Поймите это предложение наоборот, то есть все эти три состояния являются бездействующими состояниями в глазах операционной системы, и одно и то жене получит права на использование ЦП

Посмотрите на [Статус потока на языке Java] в правой части рисунка выше, и далее кратко, кроме жизни и смерти потока, нам нужно только игратьRUNNABLEа также休眠状态Преобразования достаточно, и большинство параллельных программ являются преобразованием этих двух состояний. Итак, нам нужно понять, какое время будет запускать эти переходы состояний.

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

Переходы состояний RUNNABLE и BLOCKED

Если и только одно условие перейдет из состояния RUNNABLE в состояние BLOCKED, то есть поток ожидает синхронизированную встроенную неявную блокировку; если ожидающий поток получит синхронизированную встроенную неявную блокировку, он перейдет из состояния BLOCKED в состояние RUNNABLE.

Уведомление:

Как упоминалось выше, с точки зрения общего состояния операционной системы поток, вызывающий блокирующий API, станет бездействующим (освободит права на использование ЦП), но на уровне JVM состояние потока Java не изменится, т.е. то есть состояние потока Java не изменится, он по-прежнему останется в состоянии RUNNABLE. JVM не заботится о состоянии планирования ОС. С точки зрения JVM, ожидание прав на использование ЦП (операционная система находится в исполняемом состоянии) и ожидание ввода-вывода (операционная система находится в неактивном состоянии) — все это ожидание ресурса, поэтому все они классифицируются. как ВЫПОЛНЯЕМЫЙ.

​ —— Выдержка из "Практика параллельного программирования на Java"

Переходы между состояниями RUNNABLE и WAITING

перечислитьAPI ожидания без параметра времени, он войдет в состояние ОЖИДАНИЯ из состояния РАБОТАЕТ; когда он проснется, он войдет в состояние РАБОТАЕТ из ОЖИДАНИЯ

Переходы состояний RUNNABLE и TIMED-WAITING

перечислитьAPI ожидания с параметром времени, естественно входит в состояние TIMED-WAITING из состояния RUNNABLE; когда он проснется или истечет время ожидания, он войдет в состояние RUNNABLE из TIMED_WAITING

Конверсионных API на картинке довольно много.На самом деле не переживайте.Проанализировав главы исходного кода,вы естественно их запомните.Теперь у вас есть впечатление и нода,которая знает переход состояния.


Я полагаю, что на этом этапе вы не будете так запутаны, когда будете смотреть на жизненный цикл потоков Java.Ключевым моментом является переключение между состоянием RUNNABLE и спящим.Далее давайте посмотрим, как просмотреть состояние в поток и определенные точки срабатывания кода.

Как увидеть, в каком состоянии находится поток

программный вызовgetState()метод

Класс потока также существуетgetState()Метод используется для просмотра текущего состояния потока, который должен вернуть класс перечисления, упомянутый выше.State

NEW

Как упоминалось выше, он уникален для языков программирования.После определения потока путем наследования Thread или реализации интерфейса Runnable состояние в это время — NEW.

Thread thread = new Thread(() -> {});
System.out.println(thread.getState());

RUNNABLE

называетсяstart()После метода поток находится в состоянии RUNNABLE.

Thread thread = new Thread(() -> {});
thread.start();
//Thread.sleep(1000);
System.out.println(thread.getState());

BLOCKED

В ожидании синхронизированной встроенной блокировки она будет в состоянии ЗАБЛОКИРОВАНА.

public class ThreadStateTest {

	public static void main(String[] args) throws InterruptedException {
		Thread t1 = new Thread(new DemoThreadB());
		Thread t2 = new Thread(new DemoThreadB());

		t1.start();
		t2.start();

		Thread.sleep(1000);

		System.out.println((t2.getState()));
		System.exit(0);
	}
}

class DemoThreadB implements Runnable {
	@Override
	public void run() {
		commonResource();
	}

	public static synchronized void commonResource() {
		while(true) {
			
		}
	}
}

WAITING

вызывающий потокjoin()и т. д., из состояния RUNNABLE в состояние WAITING

public static void main(String[] args) throws InterruptedException {
		Thread main = Thread.currentThread();

		Thread thread2 = new Thread(() -> {
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
        Thread.currentThread().interrupt();
				e.printStackTrace();
			}
			System.out.println(main.getState());
		});
		thread2.start();
		thread2.join();
	}

TIMED-WAITING

называетсяsleep(long)и другие методы, поток переходит из состояния RUNNABLE в TIMED-WAITING

public static void main(String[] args) throws InterruptedException {
		Thread thread3 = new Thread(() -> {
			try {
				Thread.sleep(3000);
			} catch (InterruptedException e) {
        // 为什么要调用interrupt方法?
				Thread.currentThread().interrupt();
				e.printStackTrace();
			}
		});
		thread3.start();

		Thread.sleep(1000);
		System.out.println(thread3.getState());
	}

TERMINATED

После того, как поток будет выполнен, он естественным образом достигнет состояния TERMINATED.

Thread thread = new Thread(() -> {});
thread.start();
Thread.sleep(1000);
System.out.println(thread.getState());

Выше это просмотр ветки в программе.Сами тест напишите,чтобы посмотреть в порядке ли статус.Как реальная программа позволяет вам добавлять столько бесполезного кода,так,Куйхуа,подавайте квашеную капусту(jstack)

команда jstack для просмотра

Я полагаю, вы слышали об этом, команда jstack более мощная, вы можете не только просматривать текущее состояние потока, но и просматривать информацию о стеке потока, такую ​​как стек вызовов, блокировка и так далее.

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

Для получения дополнительных функций, пожалуйста, проверьте это самостоятельно.Я напишу отдельную статью, чтобы научить вас, как использовать jstack для просмотра информации о стеке потоков.

Arthas

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

Просмотр сведений о стеке потоков очень удобен:alibaba.GitHub.IO/art has/he и hot…

Я полагаю, вы подтвердили свои глаза с Артасом

Даже если вы закончили говорить о состоянии жизненного цикла потока в целом, задайте себе еще вопросы при написании параллельных программ:

В какое состояние вызов API переводит ваш поток?

Спросите себя несколько раз, и вы, естественно, вспомните картинку выше.

вопрос души

  1. Почему Thread.currentThread().interrupt(); вызывается после вызова Thread.sleep и перехвата исключения

  2. Есть только один случай ввести BLOCKED, то есть дождаться синхронизированной блокировки монитора, а затем вызвать метод Lock.lock() в JUC.Если поток ожидает этой блокировки, каково состояние этого потока? Почему?

    public class ThreadStateTest {
    
    	public static void main(String[] args) throws InterruptedException {
    		TestLock testLock = new TestLock();
    
    		Thread thread2 = new Thread(() -> {
    			testLock.myTestLock();
    		}, "thread2");
    
    		Thread thread1 = new Thread(() -> {
    				testLock.myTestLock();
    			}, "thread1");
    
    		thread1.start();
    		Thread.sleep(1000);
    
    		thread2.start();
    		Thread.sleep(1000);
    
    		System.out.println("****" + (thread2.getState()));
    
    		Thread.sleep(20000);
    	}
    }
    
    @Slf4j
    class TestLock{
    	private final Lock lock = new ReentrantLock();
    
    	public void myTestLock(){
    		lock.lock();
    		try{
    			Thread.sleep(10000);
    			log.info("testLock status");
    		} catch (InterruptedException e) {
    			log.error(e.getMessage());
    		} finally {
    			lock.unlock();
    		}
    	}
    }
    
  3. В чем разница между синхронизированным и заблокированным?

Ссылаться на

Спасибо старшим за изложение сути, многие параллельно написанные мной серии относятся к следующим материалам

  • Параллельное программирование на Java на практике
  • Красота параллельного программирования на Java
  • Кодируйте эффективно
  • Искусство параллельного программирования на Java
  • ......

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

Личный блог: https://dayarch.top

добавь меня в чат друга, Войдите в группу для развлечения, обучения и обмена и отметьте «войти в группу».

Добро пожаловать, чтобы продолжать обращать внимание на общественный номер: «Сун Гун И Бин».

  • Передовая технология Java для обмена галантереей
  • Резюме эффективных инструментов | Ответ на «Инструменты»
  • Анализ вопроса интервью и ответ
  • Сбор технических данных | Ответ на «данные»

Узнайте о стеке технологий Java легко и весело, думая о чтении детективных романов, и постепенно разлагайте технические проблемы, основываясь на принципах упрощения сложных проблем, конкретизации абстрактных проблем и графики.Технология постоянно обновляется, пожалуйста, продолжайте платить внимание...