слишком трудно! Интервьюер действительно хочет, чтобы я остановил текущую ветку?

Java

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

В java есть следующие 3 способа завершить запущенный поток:

  1. Используйте флаг выхода, чтобы поток завершился в обычном режиме, т. е. когда метод запуска завершится, поток завершится.
  2. Используйте метод остановки для принудительного завершения, но этот метод не рекомендуется, поскольку методы остановки, как и приостановка и возобновление, являются методами с истекшим сроком действия.
  3. Прервите поток, используя метод прерывания.

1. Непреодолимая нить

Эффект метода interrupt() не похож на оператор for+break, который немедленно останавливает цикл. Вызов метода прерывания помещает знак остановки в текущий поток, фактически не останавливая поток.

太难了!面试官居然要我停止一个正在运行的线程?

Выходной результат:

太难了!面试官居然要我停止一个正在运行的线程?

2. Определить, остановлен ли поток

Два метода предусмотрены в Thread.java Class:

  1. this.interrupted(): проверить, был ли текущий поток прерван;
  2. this.isInterrupted(): проверяет, был ли поток прерван;

Так в чем же разница между этими двумя методами?

Давайте сначала посмотрим на объяснение метода this.interrupted(): проверьте, был ли текущий поток прерван.Текущий поток относится к потоку, выполняющему метод this.interrupted().

太难了!面试官居然要我停止一个正在运行的线程?

результат операции:

??
 ??

Хотя класс Run.java вызывает следующий код на объекте потока: Thread.interrupt (), который используется позже

(" 1??" + ());
(" 2??" + ());

Чтобы определить, представлен ли объект потоком, останавливается, но представление консоли печати не останавливает поток, что также доказало объяснение метода interrupted() для проверки того, был ли текущий поток прерван. Текущий поток является основным, он никогда не останавливался, поэтому выводится результат two false.

Как заставить основной поток иметь эффект прерывания?

太难了!面试官居然要我停止一个正在运行的线程?

Эффект бега:

 ??
 ??

Метод interrupted() определяет, находится ли текущий поток в остановленном состоянии. Но почему второе логическое значение ложно? Объяснение метода interrupted в официальном справочном документе:

Проверяет, был ли текущий поток прерван. Прерванное состояние потока очищается этим методом.

Другими словами, если метод вызывается дважды подряд, второй вызов возвращает false.

Давайте посмотрим на метод inInterrupted().

太难了!面试官居然要我停止一个正在运行的线程?

результат операции:

 ??
 ??

isInterrupted() не очищает состояние, поэтому печатаются два значения true.

3. Потоки, которые можно остановить — метод исключения

С полученными ранее знаниями вы можете использовать оператор for в потоке, чтобы определить, находится ли поток в остановленном состоянии.Если он находится в остановленном состоянии, следующий код больше не может выполняться:

太难了!面试官居然要我停止一个正在运行的线程?

результат операции:

太难了!面试官居然要我停止一个正在运行的线程?

В приведенном выше примере поток останавливается, но если после оператора for есть операторы, он продолжит выполнение. См. пример ниже:

太难了!面试官居然要我停止一个正在运行的线程?

Результат выполнения с Run.java:

太难了!面试官居然要我停止一个正在运行的线程?

Как решить проблему, что инструкция продолжает работать? Взгляните на обновленный код:

太难了!面试官居然要我停止一个正在运行的线程?

Результат работы с Run.java выглядит следующим образом:

太难了!面试官居然要我停止一个正在运行的线程?

4. Остановитесь в дремоте

Если поток остановит поток в состоянии сна(), каков будет эффект?

太难了!面试官居然要我停止一个正在运行的线程?

Результат работы с Run.java:

太难了!面试官居然要我停止一个正在运行的线程?

Судя по напечатанным результатам, если поток остановлен в состоянии сна, будет введен оператор catch, а значение состояния остановки будет очищено до значения false.

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

太难了!面试官居然要我停止一个正在运行的线程?

результат операции:

太难了!面试官居然要我停止一个正在运行的线程?

5. Потоки, которые можно остановить --- грубая форсировка

Использование метода stop() для остановки потока — это очень грубая сила.

太难了!面试官居然要我停止一个正在运行的线程?

результат операции:

太难了!面试官居然要我停止一个正在运行的线程?

6. Метод stop() и исключение java.lang.ThreadDeath

Исключение java.lang.ThreadDeath вызывается при вызове метода stop(), но обычно это исключение не нужно перехватывать явно.

太难了!面试官居然要我停止一个正在运行的线程?

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

7. Снимите блокировку неблагоприятных последствий

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

public class SynchronizedObject {    private String name = "a";    private String password = "aa";    public synchronized void printString(String name, String password){        try {            this.name = name;            Thread.sleep(100000);            this.password = password;        } catch (InterruptedException e) {            e.printStackTrace();        }    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public String getPassword() {        return password;    }    public void setPassword(String password) {        this.password = password;    }}public class MyThread extends Thread {    private SynchronizedObject synchronizedObject;    public MyThread(SynchronizedObject synchronizedObject){        this.synchronizedObject = synchronizedObject;    }    public void run(){        synchronizedObject.printString("b", "bb");    }}public class Run {    public static void main(String args\[\]) throws InterruptedException {        SynchronizedObject synchronizedObject = new SynchronizedObject();        Thread thread = new MyThread(synchronizedObject);        thread.start();        Thread.sleep(500);        thread.stop();        System.out.println(synchronizedObject.getName() + "  " + synchronizedObject.getPassword());    }}

Выходной результат:

b  aa

Из-за метода stop() и метода, отмеченного в JDK как "истекший/устаревший", очевидно, что он функционально несовершенен, поэтому не рекомендуется использовать метод stop() на листах программ.

8. Используйте return, чтобы остановить поток

Комбинация метода interrupt() с return также может привести к остановке потока:

public class MyThread extends Thread {    public void run(){        while (true){            if(this.isInterrupted()){                System.out.println("线程被停止了!");                return;            }            System.out.println("Time: " + System.currentTimeMillis());        }    }}public class Run {    public static void main(String args\[\]) throws InterruptedException {        Thread thread = new MyThread();        thread.start();        Thread.sleep(2000);        thread.interrupt();    }}

Выходной результат:

...Time: 1467072288503Time: 1467072288503Time: 1467072288503线程被停止了!

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