Это зависит от того, как вы хотите, чтобы 10 потоков «заканчивались», и от того, как вы запускаете потоки.
Я рекомендую создать ExecutorService
и записать ваши "нити" в виде Runnable
реализаций. Эти Runnable
объекты должны отвечать на вызовы interrupt()
в своем потоке выполнения, прерывая свою задачу, очищая и выходя из метода run
как можно быстрее.
Отправьте эти Runnable
задачи на ExecutorService
, затем вызовите awaitTermination
, все в главном потоке. Когда пользователь нажимает кнопку «Стоп», вызовите shutdown
или shutdownNow
по желанию на ExecutorService
(из потока рассылки событий).
Если вы вызовете shutdownNow
в службе исполнителя, она уведомит запущенные задачи, прерывая их потоки. Если вы позвоните shutdown
, это позволит выполнять задачи без перерыва. В любом случае, ваш основной поток будет блокироваться на awaitTermination
до тех пор, пока все задачи не будут выполнены (или не истечет срок).
Конечно, вы можете создавать и управлять всеми потоками самостоятельно, используя join
. Главное - сделать потоки прерываемыми, если вы хотите остановить их преждевременно.