2013-05-05 2 views
1

У меня есть программа, которая создает 10 потоков, и каждый поток имеет бесконечно бегущий цикл. Мне нужна помощь для эффективного использования крюка выключения, который может эффективно остановить все потоки. Поскольку я хочу сделать изящное закрытие, каждый поток должен закончить, как только он обнаружит, что флаг остановки повернут в ИСТИНА.Изящно выключение программы с несколькими потоками, имеющими бесконечный цикл while

public class SampleGSH implements Runnable{ 
    private static boolean stop = false; 
    public static void main(String[] args) { 
     for(int i = 0; i < 10;i++) { 
      Thread t = new Thread(new SampleGSH(), "name"+i); 
      t.start(); 
     } 
    } 

    @Override 
    public void run() { 
      Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") { 
       public void run() 
       { 
        System.out.println("*******"); 
        synchronized (this) 
        { 
         System.out.println("Turning switch off"); 
         stop = true; 
        } 
       } 
      }); 

      synchronized (this) { 
       while(!stop) 
       { 
         //Some logic which should not be killed abruptly once it starts running, a graceful shut down will not allow this code to start 
       } 
      } 
    } 
} 

Любая помощь будет по достоинству оценена.

ответ

2

Это FAQ. Если у вас есть поля, разделяемые между несколькими потоками, их необходимо синхронизировать. В этом случае ваш stop должен быть volatile. Без этого нет ничего, что гарантирует, что потоки будут видеть значение stop, изменить на true. См. this tutorial для получения информации об атомарном доступе.

См: Using boolean var for stopping threads

Пара Другие комментарии:

  • Если вы начинаете количество потоков, вы должны рассмотреть возможность использования ExecutorService
  • Вашего while цикла находится внутри synchronized блока. Это ничего не делает, и поле stop не получит синхронизацию памяти, так как она обновляется снаружи внутри блока.
  • Другой способ остановить нить будет interrupt(). См. this tutorial.

    while (!thread.currentThread().isInterrupted()) { 
        ... 
    } 
    ... 
    t.interrupt(); 
    
0

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

Что-то вроде этого:

import java.util.ArrayList; 
import java.util.List; 

public class SampleGSH extends Thread { 

    public boolean stop = false; 
    private static List<SampleGSH> threads = null; 

    public static void main(String[] args) { 

     threads = new ArrayList<SampleGSH>(); 

     int numThreads = 10; 
     for (int i = 0; i < numThreads; i++) { 
      SampleGSH t = new SampleGSH(); 
      threads.add(t); 
      t.start(); 
     } 

     Runtime.getRuntime().addShutdownHook(new Thread("shutdown thread") { 
      public void run() { 
       System.out.println("*******"); 
       for (SampleGSH t : threads) { 
        t.stop = true; 
       } 
      } 
     }); 
    } 

    @Override 
    public void run() { 
     { 
      while (!stop) { 
       // Some logic which should not be killed abruptly once it starts 
       // running, a graceful shut down will not allow this code to 
       // start 
      } 
     } 
    } 
} 
+0

Или просто используйте методы thread.interrupt() и thread.isInterrupted() вместо этого, как предлагает @Gray. –

1

Забудьте, что addShutdownHook ... пустую болтовню держать его просто ...

  1. сделать статический stop переменного летучего ...

  2. затем добавьте этот метод в SampleGSH ...

    public void shutdown() { stop = true; }

  3. затем вызвать его, когда вы хотите, чтобы остановить темы!

Смежные вопросы