Исполнитель, подходящий для небезопасного кода

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

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


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

будет ли связь между вызывающим абонентом и потоком из пула?

Andrew Tobilko 06.11.2018 11:27

Я имею в виду, что Executor полностью потокобезопасен и не будет взаимодействовать с вашими потоками, если задачи, которые вы отправляете, этого не делают. Другими словами, все зависит от типа задач, которые вы ему даете.

Andrew Tobilko 06.11.2018 11:31

Я не уверен, что использование потока Один является правильным здесь, вам, вероятно, придется многое изменить позже. Вместо того, чтобы сейчас выполнять все в одном потоке, я бы предпочел использовать основной поток + один рабочий поток, работающий за раз. Основной поток может вызывать методы блокировки для получения результатов задачи (например, Future.get). Это должно свести параллелизм к минимуму, но позже вам не придется менять всю архитектуру.

kapex 06.11.2018 11:53

Может быть, Гуавы MoreExecutors.html # sameThreadExecutor ()?

rkosegi 06.11.2018 12:01
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
4
4
515
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

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

Я уже использую шаблон Скромный объект [вопрос обновлен].

Raedwald 06.11.2018 11:42
Ответ принят как подходящий

Если коду действительно нужны Только и 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() для всех отправленных задач, все изменения любых общих объектов будут безопасно опубликованы, и поток, выполняющий модульные тесты, может безопасно проверить эти общие объекты.

Другие вопросы по теме