【问题标题】:Difference between Executors.newFixedThreadPool(1) and Executors.newSingleThreadExecutor()Executors.newFixedThreadPool(1) 和 Executors.newSingleThreadExecutor() 的区别
【发布时间】:2014-02-13 13:45:20
【问题描述】:

我的问题是:使用Executors.newFixedThreadPool(1)?? 是否有意义。在两个线程(main + oneAnotherThread)场景中,使用执行器服务效率高吗?通过调用new Runnable(){ } 直接创建一个新线程比使用ExecutorService 更好吗?在这种情况下使用 ExecutorService 有什么好处和坏处?

PS:主线程和 oneAnotherThread 不访问任何公共资源。

我已经通过了:What are the advantages of using an ExecutorService?。和Only one thread at a time!

【问题讨论】:

    标签: java multithreading executor


    【解决方案1】:

    使用 Executors.newFixedThreadPool(1) 有意义吗??

    是的。如果要按到达顺序处理所有提交的任务,这是有道理的

    在两个线程(main + oneAnotherThread)的场景下,使用执行器服务效率高吗?通过调用 new Runnable(){ } 直接创建新线程是否比使用 ExecutorService 更好?

    我更喜欢 ExecutorServiceThreadPoolExecutor,即使是 1 个线程。

    请参阅下面的 SE 问题,了解 ThreadPoolExecutor 相对于新 Runnable() 的优势:

    ExecutorService vs Casual Thread Spawner

    在这种情况下使用 ExecutorService 有什么好处和坏处?

    查看有关 ExexutorService 用例的相关 SE 问题:

    Java's Fork/Join vs ExecutorService - when to use which?

    关于您在主题行中的查询(来自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 关于异同的回答。

    【讨论】:

      【解决方案2】:

      直接调用new Runnable(){}创建新线程比使用ExecutorService好吗?

      如果要在线程编译后对返回的结果进行计算,可以使用Callable接口,该接口只能与ExecutorService一起使用,不能与new Runnable(){}一起使用。 ExecutorService 的 submit() 方法以 Callable 对象为参数,返回 Future 对象。在此 Future 对象上,您检查任务是否已在不使用 isDone() 方法的情况下完成。您也可以使用 get() 方法获取结果。 在这种情况下,ExecutorService 比新的 Runnable(){} 更好。

      【讨论】:

        【解决方案3】:

        有时需要使用Executors.newFixedThreadPool(1)来确定队列中的任务数

        private final ExecutorService executor = Executors.newFixedThreadPool(1);
        
        public int getTaskInQueueCount() {
            ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) executor;
            return threadPoolExecutor.getQueue().size();
        }
        

        【讨论】:

          【解决方案4】:

          使用Executors.newFixedThreadPool(1)有意义吗?

          它与Executors.newSingleThreadExecutor() 基本相同,只是后者不可重新配置,如javadoc 中所示,而前者是如果您将其转换为ThreadPoolExecutor

          在两个线程(main + oneAnotherThread)场景下,使用执行器服务效率高吗?

          执行器服务是一个非常薄的线程包装器,它极大地促进了线程生命周期管理。如果您唯一需要的是new Thread(runnable).start(); 并继续前进,那么就不需要 ExecutorService。

          在任何最真实的情况下,监控任务生命周期的可能性(通过返回的Futures),执行程序将根据需要重新创建线程以防未捕获的异常,性能回收线程的收益与创建新线程等相比,使执行器服务成为更强大的解决方案,而额外的成本却很少。

          底线:我认为使用执行器服务与线程相比没有任何缺点。

          The difference between Executors.newSingleThreadExecutor().execute(command) and new Thread(command).start(); 分析了两个选项在行为上的细微差别。

          【讨论】:

          • 感谢您的回答。您所说的可重新配置究竟是什么意思?
          • ((ThreadPoolExecutor) fixedThreadPool).setMaximumPoolSize(10); 不再是单线程池了。
          • 否 - 它将重新配置现有的一个以允许多个线程。
          • 这篇博文描述了使用Executors.newSingleThreadExecutor() 的潜在缺点:farside.org.uk/201309/learning_from_bad_code。推荐使用Executors.newFixedThreadPool(1)
          • @robinhowlett 很有趣——虽然这里描述的问题只有在你放弃对执行程序的引用而没有调用关闭时才会出现,这可能是第一个实例中的错误。如果您在字段中保留对执行程序的引用并正确管理其生命周期,您将不会遇到问题。
          猜你喜欢
          • 1970-01-01
          • 2011-07-09
          • 2018-08-05
          • 2022-10-01
          • 2018-08-02
          • 2015-07-13
          • 2011-08-31
          • 2013-06-18
          • 2017-03-26
          相关资源
          最近更新 更多