1

Я кодирую программу, которая генерирует случайное число между 1 и 1000. Затем он использует пул потоков из трех потоков для поиска определенных диапазонов чисел в более широком диапазоне от 1 до 1000. Потоки проверяют каждый номер в своем диапазоне и сравнивают его со случайным целевым номером, если он соответствует, сообщение в консоли говорит об этом. Если номер не совпадает, это также отражается в сообщении на консоли. Я пытаюсь выяснить, как закончить программу, как только достигнут целевой номер, и не продолжать анализировать числа, даже если цель уже найдена. Спасибо.Как остановить потоки в Java

Это FINDit класс:

/** fill in later */ 
public class FindIt extends Thread 
{ 
    private int numToFind; 
    private int numToStart; 
    private int numToEnd; 

    public FindIt(int nF, int nS, int nE) 
    { 
     numToFind = nF; 
     numToStart = nS; 
     numToEnd = nE; 
    } 

    public void run() 
    { 
     int counter = 0; 

     int numAt = numToStart; 

     for (int i = 0; i < (numToEnd - numToStart) + 1; i++) 
     { 
      counter++; 

      if (counter == 10) 
      { 
       counter = 0; 
       Thread.yield(); 
      } 

      if (numAt++ == numToFind) 
      { 
       System.out.println("The target number, " + numToFind + ", has been found by " + Thread.currentThread().getName() + "."); 
      } 

      else 
      { 
       System.out.println(Thread.currentThread().getName() + " has analyzed the number " + (numAt - 1) + " - not the target number."); 
      } 

     } 
    } 
} 

Это программа с основным методом:

import java.util.Random; //imports Java's Random class 
import java.util.concurrent.*; 

/** fill in later */ 
public class NumberSearch 
{ 
    public static void main(String [] args) 
    { 
     Random r = new Random(); //creates an instance of the Random class 
     int randomNum = r.nextInt(1001); //declares the integer randomNum and initilizes it to be a random interger in the range 0 inclusive to 1001 exclusive 

     ExecutorService executor = Executors.newFixedThreadPool(3); 

     FindIt find1 = new FindIt(randomNum, 0, 349); 
     FindIt find2 = new FindIt(randomNum, 350, 699); 
     FindIt find3 = new FindIt(randomNum, 700, 1000); 

     executor.execute(find1); 
     executor.execute(find2); 
     executor.execute(find3); 

     executor.shutdown(); 
    } 
} 
+1

Возможный дубликат [? Как правильно остановить поток в Java] (http://stackoverflow.com/questions/10961714/how-to-properly-stop -the-thread-in-java) –

+0

@Ravindrababu: имейте в виду, что принятый ответ по этому вопросу не обрабатывает случай, когда задача выполняется в потоковом пуле, при использовании исполнителей вся процедура ручного волатильного флага не работает. –

+0

Хорошо. Я отозвал свой голос. –

ответ

4

Две вещи необходимы:

  • сделать ваши задачи в ответ на прерывание путем проверки Thread.currentThread().isInterrupted() и возврата задачи при обнаружении прерывания.

  • Используйте метод shutdownNow ExecutorService, чтобы прервать текущие запущенные задачи. Метод shutdown заставляет исполнителя останавливать прием новых задач, но задачи, которые уже переданы исполнителю, выполняются до завершения.

Не подклассы. Для этого вам следует расширить Runnable или Callable, чтобы определить задачи, представленные Исполнителю. Subclassing Thread означает, что задача выделяет поток ОС, который не нужен, так как фактические потоки уже созданы в поточном пуле. В этом примере, поскольку вы вычисляете число в своих задачах, может иметь смысл использовать Callable.

Существует существующий класс в java.util.concurrent, который предназначен для такого рода вещей. Пример отмены задач после того, как был найден ответ, указан в API documentation for ExecutorCompletionService.

FINDit изменен для обнаружения прерывания:

public class FindIt implements Runnable 
{ 
    private int numToFind; 
    private int numToStart; 
    private int numToEnd; 

    public FindIt(int nF, int nS, int nE) 
    { 
     numToFind = nF; 
     numToStart = nS; 
     numToEnd = nE; 
    } 

    public void run() 
    { 
     int counter = 0; 

     int numAt = numToStart; 

     for (int i = 0; i < (numToEnd - numToStart) + 1; i++) 
     { 
      if (Thread.currentThread().isInterrupted()) { 
       System.out.println(Thread.currentThread().getName() 
       + " detected interruption, exiting"); 
       return; 
      } 
      counter++; 

      if (counter == 10) 
      { 
       counter = 0; 
       Thread.yield(); 
      } 

      if (numAt++ == numToFind) 
      { 
       System.out.println("The target number, " + numToFind + ", has been found by " + Thread.currentThread().getName() + "."); 
      } 

      else 
      { 
       System.out.println(Thread.currentThread().getName() + " has analyzed the number " + (numAt - 1) + " - not the target number."); 
      } 

     } 
    } 
} 
+0

Это делает работу shutdownNow() корректной, но я не могу сразу ее вызвать без остановки потоков мгновенно. Как мне обратиться за вызовом shutdownNow(), когда номер найден? –

+0

@ B.Freeman: вы можете дождаться, когда будете называть shutdownNow, пока не получите ответ. я сделал что-то подобное, но без исполнителя [здесь] (http://stackoverflow.com/q/36872621/217324). Но в этом случае я буду использовать «Будущее» и вызывать shutdownNow, как только будущее вернется. также здесь [ответ с использованием Future and Callable] (http://stackoverflow.com/a/35563988/217324). –