2013-11-13 2 views
1

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

Я в предположении, что если выполнение Runnable заканчивается внутри Thread, что тогда как Thread и Runnable будут уничтожены, как код внутри Runnable линейный код, а может быть, некоторые вызовы функций, но определенно нет петли.

Проблема в том, что Thread все еще работает, хотя я думаю, что этого не должно быть.

Создание RunnableProcessor:

Controller.getInstance().getNamedThreadFactory().addThreadName("EST: " + runnableProcessor.toString()); 
Controller.getInstance().getExecutorService().execute(runnableProcessor); 

RunnableProcessor Класс:

public class RunnableProcessor<T> implements Runnable { 
    private final Processor<T> processor; 
    private final T object; 

    public RunnableProcessor(final Processor<T> processor, final T object) { 
     this.processor = processor; 
     this.object = object; 
    } 

    @Override 
    public void run() { 
     processor.process(object); 
    } 

    @Override 
    public String toString() { 
     return "RunnableProcessor(\"" + processor + "\", \"" + object.toString() + "\")"; 
    } 
} 

Примером такой Processor, а именно InputProcessor:

public class InputProcessor implements Processor<File> { 
    private static final String PDF = "pdf"; 

    @Override 
    public void process(File file) { 
     if (new CustomPath(file).getExtension().equalsIgnoreCase(PDF)) { 
      processPdf(file); 
     } 
     else { 
      processImage(file); 
     } 
    } 

    private void processPdf(final File file) { 
     System.out.println("Processing " + file.toString()); 
     FileEditor.convert(file); 
     Utils.move(file.toPath(), new File(Controller.DONE_URL + File.separator + file.getName()).toPath()); 
     System.out.println("Processed"); 
    } 

    private void processImage(final File file) { 
     //Skew detection 
     System.out.println("Rotating " + file.toString()); 
     SkewDetector skewDetector = new SkewDetector(file); 
     File rotatedFile = skewDetector.detect(); 
     Utils.move(rotatedFile.toPath(), new File(Controller.ROTATED_INPUT_URL + File.separator + rotatedFile.getName()).toPath()); 
     System.out.println("Rotated"); 
    } 

    @Override 
    public String toString() { 
     return "InputProcessor"; 
    } 
} 

Ничто в кодовых блоков исполнение, которое находится в t в его случае конкретные строки Processed или Rotated все печатаются до System.out, после чего конкретный Thread все еще не умирает. Это, например, один из потоков, которые все еще живы, хотя завершение выполнения Runnable, это имя: EST: RunnableProcessor("InputProcessor", "D:\OCR\renamed_input\682-converted.tiff").

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

Может кто-нибудь помочь выяснить, что именно происходит?

+0

В какой пакет входит ваш 'Контроллер'? – anoopelias

ответ

2

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

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

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

void run() { 
    innerRunner.run(); // the wrapped runner 
    doneFlag = true; // a boolean indicating the status 
} 
+0

Правильно, я использую его для создания фиксированных чисел 'k' потоков. – skiwi

+0

Итак, нити никогда не уничтожаются сами по себе (только «ExecutorService» контролирует это ... Тогда, возможно, я реализую это неправильно, то есть используя имена, которые не имеют смысла в этом контексте. – skiwi

+0

Теперь я получаю то, ваши имена. Вероятно, это не сработает, так как явно является задачей ExecutorService управлять своими потоками. – user1252434

1

Вам может понадобиться вызвать

Controller.getInstance().getExecutorService().shutdown(); 
Controller.getInstance().getExecutorService().awaitTermination(); 

перегрузить пула потоков.

+0

Должен ли я использовать оба оператора или только один из них в зависимости от того, как я хочу завершить работу службы-исполнителя? – skiwi

+0

В большинстве случаев вам понадобятся оба - первый сигнал, чтобы прекратить принимать новые задания и продолжать выполнение, т. Е. Если это конец вашего 'main()' ваше приложение выйдет. Второй ждет завершения незавершенных работ. –

0

используется пул потоков, которые создают фиксированное количество потоков. Повторное использование пула потоков создало потоки для выполнения задач (Runnable, Callable). Вы не можете явным образом уничтожать потоки, потому что потоки являются управляемым пулом потоков.

Как вы сказали @Andrey Chaschev вы должны назвать его:

Controller.getInstance().getExecutorService().shutdown(); 
Controller.getInstance().getExecutorService().awaitTermination(); 

для прекращения нитками.

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

  • Нет связанных вопросов^_^