2014-10-30 3 views
1

Я пытаюсь выяснить, как потоки работают на Java. Я хочу понять, как я могу прервать поток, который был создан для запуска другого терминального процесса. У меня есть следующие темы:Как прервать/убить зависающую нить в Java?

  • основной поток
  • свинг нить - управляет графического интерфейса пользователя
  • терминальную нить - запускает терминальную процесс

Терминал процесс должен подавать свой выход во входной поток конечной резьбы. Мне удалось сделать это через цикл while. Тем не менее, это приведет к зависанию потока, если процесс терминала застрял (например, для ожидания ввода пользователя).

Мой вопрос заключается в два раза:

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

Ниже код является исполняемой реализацией запустить поток, который в своей очереди запустить терминальный процесс:

public void run(){ 
    ProcessBuilder pb=new ProcessBuilder("Enter a terminal process that hangs here"); 
    pb.redirectErrorStream(true); 

    Process pr; 
    try { 
     pr = pb.start(); 
     BufferedReader in = new BufferedReader(new 
     InputStreamReader(pr.getInputStream())); 
     String line; 
     try { 
      while ((line = in.readLine()) != null && !Thread.currentThread().isInterrupted()) { 
       System.out.println(line); 
      } 
      pr.waitFor(); 
     } catch (InterruptedException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 
     System.out.println("ok!"); 
     in.close(); 
     //System.exit(0); 
    } catch (IOException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
} 

Я ожидал, что для Thread.currentThread() isInterrupted()., чтобы остановить цикл и обеспечить прерывание. Однако, это не будет прерывать, когда я назвал прерывание с помощью кода ниже:

JButton btnKillThreads = new JButton("Kill Threads"); 
btnKillThreads.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent arg0) { 
     for (Thread thread : threads){ 
      thread.interrupt(); 
     } 
    } 
}); 

А вот код, который создал поток для полноты:

JButton btnStartConversion = new JButton("Start Thread"); 
btnStartConversion.addActionListener(new ActionListener() { 
    public void actionPerformed(ActionEvent e) { 
     Runnable rt = new Thread1(); 
     Thread t = new Thread(rt); 
     t.start(); 
     threads.add(t); 
    } 
}); 

ответ

2

Я думаю, что у вас есть хорошее начало. Единственная проблема заключается в том, что Thread.interrupt() не остановит процесс. Если поток заблокирован in.readLine(), он не выйдет, пока процесс не выдаст результат, и нить получила возможность проверить isInterrupted().

Если вы хотите, чтобы остановить этот процесс, в дополнение к вызову Thread.interrupt() вам нужно позвонить Process.destroy():

class MyRunnable implements Runnable { 

    private Process pr; 

    public void run() { 

     // ... 

     pr = pb.start(); 
    } 

    public shutdown() { 
     pr.destroy(); 
     interrupt(); 
    } 
} 

Вместо регистрации нить в списке вы должны зарегистрировать MyRunnable и вызвать shutdown() на Это.

Что касается поведения нити на System.exit(), все потоки будут уничтожены. Однако использование System.exit() считается плохим, потому что оно завершает работу приложения, не давая ниткам возможность отключиться изящно.Звуковая инженерная практика состоит в том, чтобы продумать изящное закрытие и использовать System.exit() только в крайнем случае.

+0

Спасибо. Это сделал трюк! Не могли бы вы посоветовать вторую часть вопроса? Если я выйду из программы, не закрывая нити, они будут продолжать работать? Предположим, что я выхожу с помощью system.Exit (0). – user3804927

+0

Я добавил объяснение. –

+0

Спасибо. Я бы поднял, но у меня пока недостаточно активных представителей. Я вернусь, когда я это сделаю. благодаря! – user3804927

0

Изменить состояние в ваш цикл while:

while ((line = in.readLine()) != null && !Thread.currentThread().isInterrupted()) { 
    System.out.println(line); 
} 
+0

Пробовал, все еще не сработает. – user3804927

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