37

Я работаю над многопоточным проектом, в котором мне нужно запускать многозадачные потоки, чтобы измерять конечную производительность моего клиентского кода, поскольку я выполняю тестирование нагрузки и производительности. Так что я создал ниже код, который использует ExecutorService -ExectuorService vs ThreadPoolExecutor (который использует LinkedBlockingQueue)

Ниже приведен код, который использует ExecutorService -

public class MultithreadingExample { 

    public static void main(String[] args) throws InterruptedException { 

     ExecutorService executor = Executors.newFixedThreadPool(20); 
     for (int i = 0; i < 100; i++) { 
      executor.submit(new NewTask()); 
     } 

     executor.shutdown(); 
     executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    } 
} 

class NewTask implements Runnable { 

    @Override 
    public void run() { 
     //Measure the end to end latency of my client code 
    } 
} 

Постановка задачи: -

Теперь я читал какую-то статью в интернете. Я узнал, что есть

ThreadPoolExecutor как хорошо. Поэтому я смутился тем, кого я должен использовать.

Если я заменить выше код from-

ExecutorService executor = Executors.newFixedThreadPool(20); 
    for (int i = 0; i < 100; i++) { 
     executor.submit(new NewTask()); 
    } 

to-

BlockingQueue<Runnable> threadPool = new LinkedBlockingQueue<Runnable>(); 

ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, TimeUnit.MILLISECONDS, threadPool); 

tpExecutor.prestartAllCoreThreads(); 

    for (int i = 0; i < 100; i++) { 
     tpExecutor.execute(new NewTask()); 
    } 

то, что будет делать какие-либо изменения? Я пытаюсь понять, в чем разница между моим исходным кодом, который использует ExecutorService, и новым кодом, который я вставил, который использует ThreadPoolExectuor? Некоторые из моих товарищей по команде сказали, что второй (ThreadPoolExecutor) - правильный способ использования?

Может ли кто-нибудь прояснить эту вещь для меня? Спасибо за помощь.

ответ

19

то это будет иметь значение?

Это сделает ваш код более сложным для небольшой выгоды.

Я пытаюсь понять, в чем разница между моим исходным кодом, использующим ExecutorService, и новым кодом, который я вставил, который использует ThreadPoolExectuor?

Рядом ни с чем. Executors создает ThreadPoolExecutor для выполнения реальной работы.

Некоторые из моих товарищей по команде заявили, что второй (ThreadPoolExecutor) является правильным способом использования?

Просто потому, что это сложнее, это не значит, что это правильно. Дизайнеры предоставили методы Executors.newXxxx, чтобы сделать жизнь проще для вас и потому, что они ожидали, что вы будете использовать эти методы. Я предлагаю вам использовать их также.

+0

Вы говорили о небольшой пользе? Что это вообще такое? А за сценой исполнители называли ThreadPoolExecutor? Но я считаю, что он использует Unbounded queue, который немного медленный, я думаю? Поправьте меня, если я ошибаюсь. – 2013-04-23 06:01:56

+0

Небольшое преимущество - вы можете играть с аргументами конструктора, но это, как правило, не очень хорошая идея. Вы предоставили ту же неограниченную очередь, поэтому я не вижу вашей точки. Если бы это было медленно, зачем дизайнеры его использовали? –

+0

Существует стоимость использования LinkedBoundedQueue. Это не имеет никакого отношения к тому, что он неограничен, и он очень мал по сравнению с затратами на передачу задач между потоками, которые, как я полагаю, вы не слишком беспокоитесь. –

7
  1. Executors#newFixedThreadPool(int nThreads)

    ExecutorService executor = Executors.newFixedThreadPool(20); 
    

в основном

return new ThreadPoolExecutor(20, 20, 
            0L, TimeUnit.MILLISECONDS, 
            new LinkedBlockingQueue<Runnable>()); 

2.

Во втором случае вы просто увеличиваете maxPoolSize до 2000, что, я сомневаюсь, вам понадобится.

58

Вот источник Executors.newFixedThreadPool:

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

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

4

Я считаю, что еще одним преимуществом является RejectionHandler. Исправьте меня, если ошиблись

1

Через 2 дня GC out of memory exception, ThreadPoolExecutor спас мою жизнь. :)

Как сказал Баладжи,

[..] еще одно преимущество есть с RejectionHandler.

В моем случае у меня было много RejectedExecutionException и с указанием (как следует) политика сброса разрешила все мои проблемы.

private ThreadPoolExecutor executor = new ThreadPoolExecutor(1, cpus, 1, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(), new ThreadPoolExecutor.DiscardPolicy()); 

Но будьте осторожны! Он работает только в том случае, если вам не нужно необходимо выполнить все темы, которые вы отправляете исполнителю.

Для получения дополнительной информации о ThreadPoolExecutor взглянуть на Darren's answer

0

В первом примере, Вы создали всего 20 темы с ниже заявление

ExecutorService executor = Executors.newFixedThreadPool(20); 

В втором примере, вы установили нить пределы диапазона, в между 20 to 2000

ThreadPoolExecutor tpExecutor = new ThreadPoolExecutor(20, 2000, 0L, 
            TimeUnit.MILLISECONDS,threadPool); 

Другие темы доступны для проце ssing. Но вы настроили очередь задач как неограниченную очередь.

ThreadPoolExecutor был бы более эффективен, если вы настроили многие или все нижеуказанные параметры.

ThreadPoolExecutor(int corePoolSize, 
       int maximumPoolSize, 
       long keepAliveTime, 
       TimeUnit unit, 
       BlockingQueue<Runnable> workQueue, 
       ThreadFactory threadFactory, 
       RejectedExecutionHandler handler) 

RejectedExecutionHandler будет полезно при установке max capacity for workQueue и ряд задач, которые были представлены Исполнителю более workQueue мощности.

Для получения более подробной информации см. Раздел Отклоненные задачи в ThreadPoolExecutor.