JUnit и параллелизм: необъяснимая ошибка - PullRequest
0 голосов
/ 29 марта 2012

Я прочитал в нескольких постах, что использование JUnit для тестирования параллелизма не является идеальным, но у меня пока нет выбора. Я только что столкнулся с исключением, которое не могу объяснить.

Я запускаю тест, где в итоге:

  • Я отправляю 1000 исполняемых файлов исполнителю
  • каждый запускаемый объект добавляет элемент в список
  • жду окончания работы исполнителя
  • JUnit сообщает мне, что в списке только 999 элементов
  • исключение не выводится в работающем блоке catch

Что может вызвать такое поведение?

Примечание: время от времени я получаю исключение. В коде есть некоторые не связанные вещи, но я оставил его там на случай, если что-то пропустил XXXQuery - это перечисление.

public void testConcurrent() throws InterruptedException {
    final int N_THREADS = 1000;
    final XXXData xxxData = new AbstractXXXDataImpl();
    final List<QueryResult> results = new ArrayList<>();
    ExecutorService executor = Executors.newFixedThreadPool(N_THREADS);
    for (int i = 0; i < N_THREADS; i++) {
        final int j = i;
        executor.submit(new Runnable() {

            @Override
            public void run() {
                try {
                    results.add(xxxData.get(XXXQuery.values()[j % XXXQuery.values().length]));
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        });
    }
    executor.shutdown();
    executor.awaitTermination(10, TimeUnit.SECONDS);
    assertEquals(N_THREADS, results.size());
}

1 Ответ

2 голосов
/ 29 марта 2012

Нельзя добавить к results ArrayList в вашем методе Runnable.run() в несколько потоков без синхронизации вокруг него.

Сообщение об ошибке подтверждения показывает, что, хотя N_THREADS звонки на add() были сделаны, ArrayList получил меньше записей из-за условий гонки параллелизма.

Я бы использовал окончательный массив вместо списка. Что-то вроде:

final QueryResult[] results = new QueryResult[N_THREADS];
for (int i = 0; i < N_THREADS; i++) {
    ...
        public void run() {
            results[j] = data.get(Query.values()[j % Query.values().length]);
        }

Кроме того, я не совсем понимаю XXXQuery.values(), но я бы включил его в переменную над циклом, если она не меняется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...