Как быстро и чисто прервать поток в Java? - PullRequest
28 голосов
/ 18 сентября 2008

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

Как я могу сделать что-то подобное?

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

Ответы [ 15 ]

1 голос
/ 18 сентября 2008

Способ, которым я реализовал нечто подобное в прошлом, заключается в реализации метода shutdown() в моем подклассе Runnable, который устанавливает переменную экземпляра с именем should_shutdown в true. Метод run() обычно что-то делает в цикле и периодически проверяет should_shutdown, а когда он равен true, возвращает или вызывает do_shutdown(), а затем возвращает.

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

Я бы не рекомендовал использовать Thread.stop, так как это было устаревшим в прошлый раз, когда я проверял.

Edit:

Прочтите ваш комментарий о том, как ваш рабочий поток просто вызывает другой метод, выполнение которого занимает некоторое время, поэтому вышеприведенное неприменимо. В этом случае ваши единственные реальные варианты - попытаться позвонить по номеру interrupt() и посмотреть, окажет ли он какое-либо влияние. Если нет, подумайте о том, чтобы как-то вручную вызвать функцию, которую вызывает вызов вашего рабочего потока. Например, звучит так, будто он выполняет какой-то сложный рендеринг, поэтому, возможно, уничтожьте холст и заставьте его сгенерировать исключение. Это не очень хорошее решение, но, насколько я могу судить, это единственный способ остановить поток в подобных ситуациях.

0 голосов
/ 30 октября 2008

Правильный ответ - не использовать поток.

Вы должны использовать Executors, посмотрите пакет: java.util.concurrent

0 голосов
/ 18 сентября 2008

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

Извините, после перечитывания вашего вопроса ни это, ни какое-либо другое предложение 'check variable' не решит вашу проблему.

0 голосов
/ 18 сентября 2008

Поскольку вы имеете дело с кодом, у вас нет доступа к нему, вероятно, вам не повезло. Стандартная процедура (как указано в других ответах) - наличие флага, который периодически проверяется запущенным потоком. Если флаг установлен, выполните очистку и выйдите.

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

Этот метод небезопасен. Остановка потока с помощью Thread.stop приводит к тому, что он разблокирует все заблокированные мониторы (как естественное следствие непроверенного исключения ThreadDeath, распространяющегося вверх по стеку). Если какой-либо из объектов, ранее защищенных этими мониторами, находился в несогласованном состоянии, поврежденные объекты становятся видимыми для других потоков, что может привести к произвольному поведению.

Более подробную информацию по этой теме можно найти здесь .

Один абсолютно верный способ выполнить ваш запрос (хотя это не очень эффективный способ сделать это) - запустить новый процесс Java через Runtime.exec () , а затем остановить этот процесс как необходимо через Process.destroy () . Однако совместное использование состояний между процессами не совсем тривиально.

0 голосов
/ 18 сентября 2008

Может быть, это может вам помочь: Как мы можем уничтожить работающий поток в Java?

Вы можете уничтожить определенный поток, установив внешнюю переменную класса.

 Class Outer
 {    
    public static flag=true;
    Outer()
    {
        new Test().start();
    } 
    class Test extends Thread
    {               
       public void run()
       {
         while(Outer.flag)
         {
          //do your work here
         }  
       }
    }
  } 

, если вы хотите остановить вышеуказанный поток, установите для переменной-флага значение false. Другой способ убить поток - это просто зарегистрировать его в ThreadGroup, а затем вызвать destroy(). Этот способ также можно использовать для уничтожения похожих потоков, создав их как группу или зарегистрируйтесь в группе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...