Исполнитель подходит для не поточно-безопасного кода - PullRequest
0 голосов
/ 06 ноября 2018

Я разрабатываю некоторый код, который в конечном итоге будет многопоточным, используя пул потоков Executor. Задачи, выполняемые пулом потоков, будут выполнять обратные вызовы и (иногда) отправлять дальнейшие задачи в очередь задач. Я хотел бы сначала разработать однопоточный код, сделать его правильно (я использую Test Driven Development) и только затем внести изменения для обеспечения безопасности потоков (блокировки и т. Д.). Для этого мне нужно Executor, которое безопасно использовать с не поточно-ориентированным кодом.

Я думаю , что означает, что мне нужен Executor, который является однопоточным. То есть это вызывает выполнение всей работы вызывающим потоком. Предоставляет ли JRE такой Executor? Или можно настроить один из Executor для работы в этом режиме?


Я уже использую шаблон тестирования Humble Object для проверки большей части моего кода однопоточным. Тем не менее, часть моего кода должна взаимодействовать с Executor или, возможно, ExecutorService, потому что это около планирования и повторное представление задач, и это будет делать это нетривиальным образом. Тестирование того, что код является проблемой здесь. Задачи обновляют общий объект, который содержит их результаты и входные данные. Я хочу отложить необходимость сделать этот общий объект поточно-ориентированным, пока у меня не будет реализован и отлажен код планирования и повторной передачи.

Ответы [ 2 ]

0 голосов
/ 06 ноября 2018

Если код действительно нуждается в только Executor, а не (гораздо более сложном) ExecutorService, легко реализовать собственный однопоточный исполнитель, который делает именно то, что нужно. Документация API Executor даже показывает вам, как это сделать:

class DirectExecutor implements Executor {
   public void execute(Runnable r) {
     r.run();
   }
}

Если для кода требуется ExecutorService, возможно , что однопотокового исполнителя, предоставленного Executors.newSingleThreadExecutor(), достаточно для тестирования не поточно-безопасного кода, несмотря на полученная программа имеет два потока (поток, выполняющий модульные тесты, и один поток пула потоков ExecutorService). Это связано с тем, что ExecutorService должен обеспечивать следующие гарантии безопасности потока :

  • Действия в потоке перед отправкой задачи Runnable или Callable в ExecutorService случайное до любое действие, выполненное этой задачей,
  • , что в свою очередь происходит до , результат получается через Future.get().

Следовательно, если поток, выполняющий модульные тесты, выполняет Future.get() для всех представленных задач, все изменения в любых общих объектах будут безопасно опубликованы, и поток, выполняющий модульные тесты, может безопасно проверять эти общие объекты.

0 голосов
/ 06 ноября 2018

Если вы планируете сначала разработать однопоточное решение, чем абстрагировать бизнес-логику от семантики Thread, то это путь. Реализуйте Callable или Runnable, которые можно тестировать без запуска нового Thread, например. используя поддельные Executor в ваших юнит-тестах.

...