Статьи о многопоточном параллелизме — как остановить потоки

Java

Автор - java-программист из Гуанчжоу. Я только что закончил полгода назад. В свободное время пишу блог. Если вы считаете, что мои статьи хорошо написаны, вы можете подписаться на мой публичный аккаунт WeChat (J2 Binbin), там будет более захватывающий контент. Я начал вести блог в августе 2018 года и надеюсь написать больше простых для понимания технических статей, чтобы поделиться ими с вами в будущем.

предисловие

   Вы когда-нибудь задумывались, как остановить нить? Многие люди сначала думают о методе Thread.stop(), но этот метод устарел и не рекомендуется, потому что этот метод вызовет проблемы с безопасностью, какие проблемы с безопасностью? Подробности будут сообщены позже. Давайте поговорим о методе Thread.interrupt(), который в настоящее время рекомендуется JDK API для остановки потоков.

Thread.interrupt()

  Поскольку поток не может быть остановлен напрямую, есть только один способ завершить поток — разрешить завершение метода run.   Thread.interrupt() означает «остановить, прервать». Но этот метод должен добавить суждение, чтобы завершить остановку потока. Как только будет обнаружено, что поток находится в прерванном состоянии, есть возможность завершить метод выполнения.    Давайте рассмотрим пример кода, чтобы увидеть, как он останавливает поток?

1. interrupt() останавливает поток
package com.bingo.thread.stopThread;

/**
 * Created with IntelliJ IDEA.
 * Description: 停止线程不推荐使用stop方法,此方法不安全,我们可以使用Thread.interrupt()
 * User: bingo
 */
public class Run {

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myThread.interrupt();
        System.out.println("end...");
    }
}


class MyThread extends Thread{

    @Override
    public void run() {
        super.run();

        for (int i = 0; i < 10000 ; i++) {

            if(this.isInterrupted()){
                System.out.println("已经是停止状态了,我要退出了");
                break;
            }
            System.out.println("i="+(i+1));
        }
    }
}

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

i=1
......
i=3102
i=3103
i=3104
i=3105
i=3106
i=3107
i=3108
end...
已经是停止状态了,我要退出了

  Результаты выполнения Мы видим, что когда цикл потока myThread достигает i=3108, он выходит из цикла, потому что поток прерывается.Этот пример является хорошим объяснением эффекта метода прерывания.

2. Прерывание может очистить замороженное состояние потока и восстановить поток в работоспособное состояние.
package com.bingo.thread.stopThread;

/**
 * Created with IntelliJ IDEA.
 * Description: interrupt可以清除线程的冻结状态,让线程恢复到可运行的状态上来。
 * User: bingo
 */
public class Run2 {

    public static void main(String[] args) {
        MyThread2 thread = new MyThread2();
        thread.start();
        thread.interrupt();
        System.out.println("main end...");
    }
}

class MyThread2 extends Thread{

    @Override
    public void run() {
        System.out.println("run begin...");
        try {
            Thread.sleep(1000000);
        } catch (InterruptedException e) {
            System.out.println("run 在沉睡中被中止,进入catch");
            e.printStackTrace();
        }
        System.out.println("run end...");
    }
}

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

main end...
run begin...
run 在沉睡中被中止,进入catch
run end...
java.lang.InterruptedException: sleep interrupted
 at java.lang.Thread.sleep(Native Method)
 at com.bingo.thread.stopThread.MyThread2.run(Run2.java:26)

Из результатов работы мы видим, что исходное время ожидания метода запуска составляет 1000 секунд, но результат печати мгновенный.Фактически, сон был прерван методом прерывания.В это время замороженное состояние поток очищается, и генерируется исключение, которое перехватывается Захват и печать информации об исключении.

Насилие Стоп - Стоп

   На следующем рисунке приведено описание метода остановки в JDK API.Вы видите, что он устарел и устарел, и расскажите нам, почему этот метод небезопасен?

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

package com.bingo.thread.stopThread;

/**
 * Created with IntelliJ IDEA.
 * Description: stop()方法为何不安全?下面例子可解答
 * User: bingo
 */
public class StopTest {

    public static void main(String[] args) {

        try {

            SynchrionzedObject object = new SynchrionzedObject();
            MyThread3 t = new MyThread3(object);
            t.start();

            Thread.sleep(500);

            t.stop();

            System.out.println(object.getUsername()+" "+object.getPassword());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class SynchrionzedObject{

    private String username = "a";

    private String password = "aa";

    public void setUsername(String username) {
        this.username = username;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

    public synchronized void printString(String username,String password){
        try {

            this.username = username;
            Thread.sleep(10000);
            this.password = password;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

class MyThread3 extends Thread{

    private SynchrionzedObject object;

    public MyThread3(SynchrionzedObject object){
        this.object = object;
    }

    @Override
    public void run() {
        object.printString("b", "bb");
    }
}

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

b aa

Из приведенного выше примера видно, что хотя метод printString заблокирован, метод run внезапно останавливается и блокировка снимается. Поток MyThread только назначает имя пользователя, но действие по назначению пароля не выполняется. В это время данные противоречивы..

Наконец

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