Как остановить потоки, созданные с помощью анонимного класса? - PullRequest
5 голосов
/ 11 декабря 2011

В моей программе много потоков в рабочем состоянии, запущенных в методе run или при вызове другого метода из run.Как остановить эти потоки?

Потоки запускаются как:

Runnable r = new Runnable() {
   @Override
      public void run() {
         // do something...
      }
};
new Thread(r,"Thread_1").start();

Другой может выглядеть так:

Runnable r = new Runnable() {
   @Override
      public void run() {
         startThread(); // another method called
      }
};
new Thread(r,"Thread_2").start();

Каков методостановка thread_1 и thread_2?

ОБНОВЛЕНИЕ

То, что я хочу, это когда я нажимаю на кнопку deactivate 3-4 потоки, работающие позади, должны быть деактивированытак что пользователь может снова запустить эти потоки, снова назначив задачу.

Ответы [ 5 ]

6 голосов
/ 11 декабря 2011

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

Попробуйте передать сообщение в Runnable, возможно, используя что-то вроде этого:

final AtomicBoolean terminate = new AtomicBoolean(false);

Runnable r = new Runnable() {
   @Override
   public void run() {
      while (!terminate.get()) {
         // do something...
      }
   }
};

new Thread(r,"Thread_1").start();
// some time later...
terminate.set(true);

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

interface CancellableRunnable extends Runnable {
   void cancel();
}

CancellableRunnable r = new CancellableRunnable() {    
   private volatile terminate = false;

   @Override
   public void run() {
      while (!terminate) {
         // do something...
      }
   }

   @Override
   public void cancel() {
      terminate = true;
   }
}

new Thread(r,"Thread_1").start();
// some time later...
r.cancel();
1 голос
/ 16 февраля 2014

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

Правильный способ прерывания потока состоит в том, чтобы выполнить метод Thread.interrupt () в этом экземпляре потока, а в самом запущенном потоке вы должны периодически проверять Thread.currentThread (). IsInterrupted (), чтобы определить, является ли поток должно быть прервано и, конечно, перехватить InterruptedException и выполнить упорядоченное завершение работы, если оно будет выдано.

Преимущество этого подхода состоит в том, что если ваш поток вызывает долгосрочный метод, надеюсь, этот метод также будет периодически проверять Thread.currentThread (). IsInterrupted () и будет отвечать на запрос прерывания, выполняя упорядоченное выполнение. завершение работы и распространение InterruptedException. Например, BlockingQueue.put действительно обнаружит запрос прерывания, выданный Thread.interrupt (). Сокеты не будут обнаруживать запрос прерывания, но будут реагировать на закрытие сокета, что можно сделать в переопределенном методе interrupt () потока.

Поскольку на самом деле нет способа вызвать метод interrupt () в анонимном потоке, вам, вероятно, не следует использовать их для длительных задач.

Рекомендую прочитать "Параллелизм Java на практике". Это отличная книга, и глава 7 «Отмена и завершение» посвящена подобным вещам. Это объясняет это намного лучше, чем я.

1 голос
/ 11 декабря 2011

Класс потока имеет метод stop(), введенный в Java 1.0 и устарел в Java 1.1.Этот метод все еще работает и убивает поток.Таким образом, вы можете остановить все свои темы, если хотите.

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

0 голосов
/ 11 декабря 2011

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

Thread thread = Thread.getCurrentThread();
if(thread.getName() == "Thread_1" || thread.getName() == "Thread_2")
{
thread.stop();
}
0 голосов
/ 11 декабря 2011

Если вы хотите принудительно прервать их, вы можете вызвать метод stop() (не рекомендуется). Просто убедитесь, что вы не открываете файлы, не выполняете ввод-вывод через сокеты, не используете блокировки и т. Д.

Лучшим подходом было бы иметь цикл while, проверяющий флаг внутри прогона:

public void run() {
   while(!stop) {
      // work
   }
}

И установите stop на true, когда хотите остановить поток. Не забудьте сделать это volatile.

...