ExecutorService.execute () молча завершает метод run () - PullRequest
0 голосов
/ 11 декабря 2018

Попытка проверить, что один из моих классов может обрабатывать доступ к нескольким потокам.У меня есть тест JUnit, в котором я создал класс для реализации Runnable и запуска своего класса.

Когда я запускаю execute, он достигает строки в методе run () и просто выходит из этого потока безсообщая о любой проблеме, я обернул ее с помощью Try-Catch (Throwable), но до сих пор нет признаков того, что пошло не так.

Вот мой код:

class ConcurrencyTests {
    class ConcurrentComponentTracker implements Runnable {
        private String component;

        ConcurrentComponentTracker(String component) {
            this.component = component;
       }

       @Override
       public void run() {
           try {
           System.out.printf("Component to track: [%s]\n", component);
           ParserHandler parserHandler = new ParserHandler();
           System.out.println(parserHandler.componentTracker(component));
           }
           catch (Throwable t) {
               t.printStackTrace();
           }
       }
   }

    @Test
    void runRunner() {
        ExecutorService executor = Executors.newFixedThreadPool(4);
        String[] componentsToTrack = {"x", "y", "z"};

        executor.execute(new ConcurrentComponentTracker(componentsToTrack[0]));
        executor.execute(new ConcurrentComponentTracker(componentsToTrack[1]));
        executor.execute(new ConcurrentComponentTracker(componentsToTrack[2]));
    }
}

И вывод:

Component to track: [x]

Component to track: [y]

Component to track: [z]

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

Ответы [ 2 ]

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

Тест JUnit должен фактически проверять и проверять результат.В этом конкретном случае ваш тест выдает результат, который должен проверить разработчик / тестировщик, поэтому это не автоматизация.Я предлагаю вам использовать Future<?> для отслеживания статуса выполнения ваших задач.Для Runnable задач get() метод Future<?> вернет null, если задача выполнена успешно, в противном случае он отправит вам исключение, заключенное в ExecutionException.Код будет выглядеть так:

@Test
void runRunner() {
    ExecutorService executor = Executors.newFixedThreadPool(3);
    String[] componentsToTrack = {"x", "y", "z"};

    assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[0]).get());
    assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[1]).get());
    assertNull(executor.submit(new ConcurrentComponentTracker(componentsToTrack[2]).get());

    // cleanup and shutdown pool
    executor.shutdown();
    try {
        executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
    } catch (InterruptedException e) {
        // ignore this
    }
}

Перед этим вы должны удалить try/catch блок внутри вашего run() метода.

Еще одна вещь, которую вы, вероятно, можете улучшить, - это сделать исполнителяполя вашего класса тестирования и управляйте им с помощью традиционного жизненного цикла JUnit, используя @BeforeClass, @Before, ... для инициализации, очистки между тестами, корректного завершения работы пула.Имейте в виду, что пулы потоков не так дешевы с точки зрения ресурсов.

Надеюсь, это поможет!

PS , если ваша цель - параллельная обработка ваших ConcurrentComponentTrackerВы можете хранить Future<?> в некоторой коллекции и запускать утверждения после того, как все задачи будут отправлены.

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

Кто бы ни ответил в комментарии, а затем удалил, это решило проблему для меня.Мой основной поток JUnit не ждал завершения других потоков.Таким образом, я добавил эти строки до конца, и все заработало, как и ожидалось:

executor.shutdown();

try {
    executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}
catch (InterruptedException e) {
    e.printStackTrace();
}
...