Разница между Executors.newFixedThreadPool(1) и Executors.newSingleThreadExecutor()

Мой вопрос: имеет ли смысл использовать Executors.newFixedThreadPool(1)??, В двухпоточных (main + oneAnotherThread) сценариях эффективно ли использовать службу executor?. Создает новый поток напрямую, вызывая new Runnable(){ } лучше, чем использовать ExecutorService? Каковы положительные и отрицательные стороны использования ExecutorService для таких сценариев?

PS: Основной поток и oneAnotherThread не имеют доступа к каким-либо общим ресурсам.

Я прошел через: Каковы преимущества использования ExecutorService?, и только одна нить за раз!

4 ответа

Решение

имеет ли смысл использовать Executors.newFixedThreadPool(1)?

Это по сути то же самое, что и Executors.newSingleThreadExecutor() за исключением того, что последний не реконфигурируем, как указано в Javadoc, тогда как первый, если вы приведете его к ThreadPoolExecutor,

В двухпоточных (main + oneAnotherThread) сценариях эффективно ли использовать службу executor?

Служба executor - это очень тонкая оболочка вокруг Thread, которая значительно облегчает управление жизненным циклом потока. Если единственное, что вам нужно, это new Thread(runnable).start(); и двигаться дальше, тогда нет реальной необходимости в ExecutorService.

В любых наиболее реальных случаях возможна возможность мониторинга жизненного цикла задач (через возвращенные Futures) тот факт, что исполнитель будет воссоздавать потоки по мере необходимости в случае неперехваченных исключений, выигрыша в производительности при переработке потоков по сравнению с созданием новых и т. д., делает службу исполнителя гораздо более мощным решением при небольших дополнительных затратах.

Итог: я не вижу никаких минусов в использовании службы исполнителя по сравнению с потоком.

Разница между Executors.newSingleThreadExecutor(). Execute(команда) и новым потоком (команда).start (); проходит через небольшие различия в поведении между двумя вариантами.

Иногда нужно использовать Executors.newFixedThreadPool(1) определить количество задач в очереди

private final ExecutorService executor = Executors.newFixedThreadPool(1);

public int getTaskInQueueCount() {
    ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
    return threadPoolExecutor.getQueue().size();
}

имеет ли смысл использовать Executors.newFixedThreadPool(1)??

Да. Это имеет смысл, если вы хотите обработать все представленные задания в порядке поступления

В двухпоточных (main + oneAnotherThread) сценариях эффективно ли использовать службу executor? Является ли создание нового потока напрямую путем вызова new Runnable(){ } лучше, чем использование ExecutorService?.

я предпочитаю ExecutorService или же ThreadPoolExecutor даже за 1 нитку.

См. Ниже вопрос SE для объяснения преимуществ ThreadPoolExecutor над новым Runnable():

ExecutorService vs Casual Spawner

Каковы положительные и отрицательные стороны использования ExecutorService для таких сценариев?

Посмотрите на связанный вопрос SE относительно вариантов использования ExexutorService:

Java Fork/Join vs ExecutorService - когда использовать какой?

Относительно вашего запроса в строке темы (из grepcode) оба одинаковы:

newFixedThreadPool API вернет ThreadPoolExecutor как ExecutorService:

public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());

а также

newSingleThreadExecutor() вернуть ThreadPoolExecutor как ExecutorService:

public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));

Я согласен с ответом @assylias относительно сходства / различия.

Является ли создание нового потока напрямую путем вызова new Runnable(){ } лучше, чем использование ExecutorService?

Если вы хотите что-то вычислить для возвращаемого результата после компиляции потока, вы можете использовать интерфейс Callable, который можно использовать только с ExecutorService, но не с новым Runnable(){}. Метод submit() в ExecutorService, который принимает объект Callable в качестве аргумента, возвращает объект Future. В этом объекте Future вы проверяете, была ли задача завершена, если не используется метод isDone (). Также вы можете получить результаты, используя метод get (). В этом случае ExecutorService лучше, чем новый Runnable(){}.

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