Как я могу прервать поток, созданный из метода?

Я знаю, что вы можете прервать поток, созданный, скажем, из исполняемого класса, но как я могу прервать этот поток, который я создал из метода? Использование volatile boolean у меня не работает, поэтому я предполагаю, что либо есть лучший способ сделать это, либо мне нужно как-то его прервать. Я не хочу прерывать все темы, только эту.

Я создал метод, который запускает Thread следующим образом:

public static void StartSyncThread() {
        new Thread() {
            public void run() {
                    isRunning = true;  // Set to true so while loop will start

                    while (isRunning) {
                        ...
                        }

            } // Close run()
        }.start();

    }

....

public static void KillSyncThread() {
    isRunning = false;
}

person Ducksauce88    schedule 18.08.2015    source источник
comment
Это должно работать. Даже если вы не указали объявление isRunning, оно будет скомпилировано только в том случае, если isRunning объявлен как boolean static для окружающего класса.   -  person Danny Daglas    schedule 19.08.2015
comment
Это не работает. Даже если логическое значение изменчиво. Когда я вызываю kill, он продолжает работать.   -  person Ducksauce88    schedule 19.08.2015
comment
Можете ли вы предоставить декларацию isRunning? Я предполагаю, что он объявлен статическим для окружающего класса. Может быть, вы случайно вставили boolean в строку isRunning = true;, а метод run() не улавливает изменения какой-то другой переменной isRunning?   -  person Danny Daglas    schedule 19.08.2015
comment
Пожалуйста, предоставьте MCVE.   -  person Sotirios Delimanolis    schedule 19.08.2015
comment
Гм ... Я не уверен, что еще предоставить. Поместите system.out внутри цикла while. Это не очень сложный пример. Я не прошу отладить мой код, я спрашиваю, как интерпретировать этот поток, учитывая, что он не находится в выполняющемся классе....   -  person Ducksauce88    schedule 19.08.2015
comment
Ваш пример работает отлично. Но я потенциально сделал много предположений. Опубликуйте MCVE, который точно отражает то, что у вас есть. Только тогда мы сможем понять, почему это не работает.   -  person Sotirios Delimanolis    schedule 19.08.2015
comment
Я не могу опубликовать код внутри цикла while, но KillSyncThread() вызывается из внешнего класса статически.   -  person Ducksauce88    schedule 19.08.2015
comment
Он не должен быть одинаковым, он должен быть репрезентативным.   -  person Sotirios Delimanolis    schedule 19.08.2015


Ответы (2)


Если вы сохраните ссылку на тему:

private static Thread myThread;

public static void StartSyncThread() {
    myThread = new Thread() {
        public void run() {    
            while (!Thread.currentThread().isInterrupted()) {
                        ...
            }

        } // Close run()
    }
    myThread.start();
}

тогда вы можете позвонить

public static void killSyncThread() {
    if (myThread != null && myThread.isAlive()) {
        myThread.interrupt();
    }
}

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

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

person Nathan Hughes    schedule 19.08.2015

В вашем коде возможно, что поток фактически не запустится до того, как вы вызовете KillSyncThread. Если это так, то поток установит для isRunning значение true, а затем продолжит работать вечно. Я бы просто установил для isRunning значение true, прежде чем вы начнете поток.

Он также не сможет остановиться, если код в

...

имеет либо бесконечный внутренний цикл, либо вызов блокирующей функции, такой как чтение сокета.

person WillShackleford    schedule 19.08.2015
comment
у меня KillSyncThread() отправляется нажатием кнопки, поэтому я вызываю Class.KillSyncThread(); и вызываю его после запуска потока. Я использую system.out. чтобы сказать, работает он или нет. - person Ducksauce88; 19.08.2015