Разница между Executors.newSingleThreadExecutor(). Execute(команда) и новым потоком (команда).start();
Ну, название говорит, что разница между Executors.newSingleThreadExecutor().execute(command)
а также new Thread(command).start();
5 ответов
Поведенчески, почти ничего.
Однако, как только у вас есть Executor
Например, вы можете отправить ему несколько задач и выполнять их одну за другой. Вы не можете сделать это просто с сырым Thread
,
Одно заметное отличие, когда вы бежите new Thread(someRunnable).start();
когда закончится работа, нить тихо умрет.
Исполнитель, тем не менее, будет сохраняться до тех пор, пока вы не выключите его. Так работает Executors.newSingleThreadExecutor().execute(command)
Когда вы думаете, что ваше приложение или JVM могут быть завершены, Исполнитель может все еще работать в фоновом потоке.
С Executor.execute
, если Error
или же RuntimeException
брошен в Executor
он будет проглочен молча, пока new Thread()
распечатает его System.err
,
Может быть много различий, но я покажу вам одно отличие, которое я считаю очень важным понять:
public void sendEventSingleThreadExecutor(Event e){
Executor.singleThreadExecutor().execute(()->{//send the event here})
}
Теперь, даже если вы звоните sendEventSingleThreadExecutor метод в 10 раз, он будет использовать только один поток для передачи их. Он не будет создавать каждый раз новый поток. Это означает, что события будут отправляться последовательно или синхронно! Вы можете прочитать больше здесь:
Теперь посмотрим на приведенный ниже пример с новой веткой.
public void sendEventThread(Event e){
Thread(//send the event here).start();
}
Если вы вызовете его 10 раз, он создаст 10 новых потоков. Это означает, что выполнение будет асинхронным! И это может быть опасно, оно может создавать множество потоков в зависимости от того, сколько раз вы вызываете функции sendEventThread.
Обратите внимание, что код предназначен только для демонстрационных целей, он может содержать синтаксическую ошибку!Если вы найдете здесь неправильное описание, я буду рад исправить его.
Дополнительная информация отсюда
newSingleThreadExecutor. Однопоточный исполнитель создает один рабочий поток для обработки задач, заменяя его, если он неожиданно умирает. Гарантируется, что задачи будут обрабатываться последовательно в соответствии с порядком, установленным очередью задач (FIFO, LIFO, порядок приоритета).[4]
[4] Однопоточные исполнители также обеспечивают достаточную внутреннюю синхронизацию, чтобы гарантировать, что любая запись в память, сделанная задачами, будет видна для последующих задач; это означает, что объекты могут быть безопасно ограничены "потоком задачи", даже если этот поток может время от времени заменяться другим.
Я предпочитаю использовать ExecutorService
или же ThreadPoolExecutor
даже для однозначных потоков. Они предлагают больше гибкости.
Посмотри на ExecutorService
& ThreadPoolExecutor
разделы в связанных вопросах SE:
Java Форк / Объединить пул, ExecutorService и CountDownLatch
Java Fork/Join vs ExecutorService - когда использовать какой?
Предположим, что вы начали с собственного потока вместо ExecutorService
, В будущем, если потребуется поддержка нескольких потоков, ExecutorService
или же ThreadPoolExecutor
предложит вам лучший контроль и гибкость для вас. Вы можете точно настроить необходимое количество параметров в этих ниже API.
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory,
RejectedExecutionHandler handler)
Executors.newSingleThreadExecutor(). Execute (команда) будет повторно использовать ранее созданный поток, он не будет создавать новый поток, как в случае нового Thread (). Если поток, который не использовался в течение шестидесяти секунд, завершается, это своего рода пул, который содержит один поток, который создает свой эквивалент newFixedThreadPool(1).