Точно так же, как люди рождаются, стареют, болеют и умирают, потоки также должны пройти через четыре разных состояния: запуск (ожидание), запуск, зависание и остановка. Этими четырьмя состояниями можно управлять с помощью методов класса Thread. Ниже приведены методы, относящиеся к этим четырем состояниям в классе Thread.
// Приостанавливаем и пробуждаем потоки
public void резюме( ); // Не рекомендуется использовать
public void suspend() // Не рекомендуется использовать
общественный статический пустотный сон (длинный миллис);
public static void Sleep(long millis, int nanos);
// Завершить поток
public void stop() // Не рекомендуется использовать
публичное недействительное прерывание ();
// Получаем статус потока
общедоступное логическое значение isAlive();
общедоступное логическое значение isInterrupted( );
общедоступное статическое логическое значение прерывается ();
// метод соединения
public void join() выдает InterruptedException;
Поток не выполняет код метода run сразу после его установления, а находится в состоянии ожидания. Когда поток находится в состоянии ожидания, вы можете установить различные атрибуты потока с помощью методов класса Thread, такие как приоритет потока (setPriority), имя потока (setName) и тип потока (setDaemon).
Когда вызывается метод start, поток начинает выполнение кода в методе run. Поток переходит в рабочее состояние. Вы можете использовать метод isAlive класса Thread, чтобы определить, запущен ли поток. Когда поток находится в состоянии выполнения, isAlive возвращает true. Когда isAlive возвращает false, поток может находиться в состоянии ожидания или в состоянии остановки. Следующий код демонстрирует переключение между тремя состояниями создания потока, запуска и остановки, а также выводит соответствующее возвращаемое значение isAlive.
общедоступный класс LifeCycle расширяет поток
{
публичный недействительный запуск()
{
интервал п = 0;
в то время как ((++n) < 1000);
}
public static void main(String[] args) выдает исключение
{
LifeCycle thread1 = новый LifeCycle();
System.out.println("isAlive: " + thread1.isAlive());
поток1.start();
System.out.println("isAlive: " + thread1.isAlive());
thread1.join(); // Дождитесь завершения потока thread1, прежде чем продолжить выполнение
System.out.println("поток1 завершился!");
System.out.println("isAlive: " + thread1.isAlive());
}
}
Результат выполнения приведенного выше кода:
Как только поток начнет выполнять метод run, он не завершится до тех пор, пока метод run не завершится. Однако во время выполнения потока есть два метода, которые можно использовать для временной остановки выполнения потока. Эти два метода — приостановка и сон. После использования приостановки для приостановки потока вы можете разбудить поток с помощью метода возобновления. После использования режима сна для перевода потока в режим сна поток может находиться в состоянии готовности только по истечении установленного времени (после завершения режима сна поток может не выполняться немедленно, а только переходит в состояние готовности, ожидая, пока система запланирует выполнение графика). .
Хотя приостановка и возобновление могут легко приостанавливать и активировать потоки, использование этих двух методов может привести к некоторым непредсказуемым событиям. Поэтому эти два метода помечены как устаревшие (протест), что указывает на то, что эти два метода могут быть удалены в будущем jdk. версий, поэтому старайтесь не использовать эти два метода для работы с потоками. Следующий код демонстрирует использование методов сна, приостановки и возобновления.
публичный класс MyThread расширяет поток
{
класс SleepThread расширяет поток
{
публичный недействительный запуск()
{
пытаться
{
сон (2000);
}
поймать (Исключение e)
{
}
}
}
публичный недействительный запуск()
{
пока (правда)
System.out.println(новый java.util.Date().getTime());
}
public static void main(String[] args) выдает исключение
{
Поток MyThread = новый MyThread();
SleepThread SleepThread = thread.new SleepThread();
SleepThread.start(); // Запускаем поток SleepThread
SleepThread.join(); // Задержка потока SleepThread на 2 секунды
поток.start();
логический флаг = ложь;
пока (правда)
{
Sleep(5000); // Задержка основного потока на 5 секунд
флаг = !флаг;
если (флаг)
поток.приостановить();
еще
поток.резюме();
}
}
}
При использовании метода сна следует учитывать два момента:
1. Метод сна имеет две перегруженные формы. Одна из перегруженных форм может задавать не только миллисекунды, но и наносекунды (1 000 000 наносекунд равны 1 миллисекунде). Однако виртуальная машина Java на большинстве платформ операционных систем не имеет точности до наносекунд. Поэтому, если для режима сна установлены наносекунды, виртуальная машина Java будет использовать миллисекунду, наиболее близкую к этому значению.
2. При использовании метода спящего режима необходимо использовать throws или try{…}catch{…}. Поскольку метод run не может использовать броски, вы можете использовать только try{…}catch{…}. Когда поток находится в режиме ожидания, спящий. выдаст InterruptedException при прерывании потока с помощью метода прерывания (этот метод будет обсуждаться в 2.3.3). Метод сна определяется следующим образом:
Есть три способа завершить поток.
1. Используйте флаг выхода, чтобы обеспечить нормальное завершение потока, то есть поток завершается после завершения метода запуска.
2. Используйте метод stop для принудительного завершения потока (этот метод не рекомендуется, поскольку остановка, как и приостановка и возобновление, также может привести к непредсказуемым результатам).
3. Используйте метод прерывания, чтобы прервать поток.
1. Завершите поток, используя флаг выхода.
Когда метод run будет выполнен, поток завершится. Но иногда метод run никогда не заканчивается. Например, потоки используются в серверных программах для мониторинга клиентских запросов или других задач, требующих циклической обработки. В этом случае эти задачи обычно помещаются в цикл, например цикл while. Если вы хотите, чтобы цикл выполнялся вечно, вы можете использовать while(true){...} для его обработки. Но если вы хотите, чтобы цикл while завершился при определенном условии, самый прямой способ — установить флаг логического типа и установить для этого флага значение true или false, чтобы контролировать, будет ли завершаться цикл while. Ниже приведен пример завершения потока с использованием флага выхода.
публичный класс ThreadFlag расширяет поток
{
общедоступный изменчивый логический выход = ложь;
публичный недействительный запуск()
{
пока (!выход);
}
public static void main(String[] args) выдает исключение
{
Поток ThreadFlag = новый ThreadFlag();
поток.start();
Sleep(5000); //Основной поток задерживается на 5 секунд
thread.exit = true // Завершить поток
поток.join();
System.out.println("Тема закрыта!");
}
}
2. Используйте метод остановки, чтобы завершить поток.
Используйте метод stop, чтобы принудительно завершить работающий или приостановленный поток. Мы можем использовать следующий код для завершения потока:
3. Используйте метод прерывания для завершения потока.
Использование метода прерывания для завершения потока можно разделить на две ситуации:
(1) Поток находится в заблокированном состоянии, например, при использовании метода сна.
(2) Используйте while(!isInterrupted()){...}, чтобы определить, прерван ли поток.
В первом случае при использовании метода прерывания метод сна выдаст исключение InterruptedException, а во втором случае поток завершится напрямую. Код ниже демонстрирует использование метода прерывания в первом случае.
публичный класс ThreadInterrupt расширяет поток
{
публичный недействительный запуск()
{
пытаться
{
Sleep(50000); // задержка 50 секунд;
}
улов (InterruptedException e)
{
System.out.println(e.getMessage());
}
}
public static void main(String[] args) выдает исключение
{
Поток потока = новый ThreadInterrupt();
поток.start();
System.out.println("Нажмите любую клавишу в течение 50 секунд, чтобы прервать поток!");
Система.в.чтение();
поток.прерывание();
поток.join();
System.out.println("Поток завершился!");
}
}
сон прерван
Ветка закрыта!
Примечание. В классе Thread есть два метода, позволяющие определить, завершен ли поток с помощью метода прерывания. Одним из них является статический метод прерывания(), а другим — нестатический метод isInterrupted(). Разница между этими двумя методами заключается в том, что прерывание используется для определения того, прерван ли текущий поток, а метод isInterrupted может использоваться для определения того, был ли прерван текущий поток. другие потоки прерываются. Поэтому while (!isInterrupted()) также можно заменить на while (!Thread.interrupted()).