【问题标题】:The difference between Executors.newSingleThreadExecutor().execute(command) and new Thread(command).start();Executors.newSingleThreadExecutor().execute(command)和new Thread(command).start()的区别;
【发布时间】:2009-12-25 09:03:08
【问题描述】:

好吧,标题说了算,Executors.newSingleThreadExecutor().execute(command)new Thread(command).start();有什么区别

【问题讨论】:

    标签: java multithreading


    【解决方案1】:

    在行为上,几乎没有。

    然而,一旦你有了一个Executor 实例,你就可以向它提交多个任务,并让它们一个接一个地执行。你不能简单地使用原始的Thread 来做到这一点。

    【讨论】:

    • “行为上,几乎没有。”是完全错误的说法。行为差异很大。请参阅下面的答案
    • 重用线程与创建多个线程怎么样?
    【解决方案2】:

    一个明显的区别是,当你运行new Thread(someRunnable).start(); 时,当runnable 完成时,线程会安静地死掉。

    Executor 将一直存在,直到您将其关闭。所以运行Executors.newSingleThreadExecutor().execute(command)当你认为你的应用程序或JVM可能已经完成时,Executor可能仍然在后台线程中运行。

    【讨论】:

    • 有趣,我无法反驳他所说的大部分内容。在submit 完成后,我无法重新创建finalize 调用。我运行了一个简单的 main 测试,委托 TPE 永远不会被 GC 处理。
    • 老实说我没有测试过。
    【解决方案3】:

    对于Executor.execute,如果在Executor 中抛出ErrorRuntimeException,它将被无声吞下,而new Thread() 会将其打印到System.err

    【讨论】:

    • 一个解决方案,为了避免异常被执行者吞下,是调用Executor.submit而不是execute,然后在你想要处理潜在的Future时调用get错误。
    • @Lii 谢谢你的澄清。
    【解决方案4】:

    可能有很多差异,但我将向您展示一个我认为非常重要的差异:

    public void sendEventSingleThreadExecutor(Event e){
      Executor.singleThreadExecutor().execute(()->{//send the event here})
    }
    

    现在,即使您调用 sendEventSingleThreadExecutor 方法10 次,它也将仅使用单个线程发送它们。它不会每次都创建一个新线程。这意味着事件将按顺序或同步发送! 您可以从here阅读更多内容:

    现在看下面带有新线程的例子

    public void sendEventThread(Event e){
      Thread(//send the event here).start();
    }
    

    如果您调用 10 次,它将创建 10 个新线程。这意味着,执行将是异步!而且它可能很危险,它可以创建很多线程,具体取决于您调用 sendEventThread 函数的次数。

    请注意,代码仅供演示,可能有语法错误! 如果您在这里发现任何错误的描述,我会很乐意更正。

    来自here的更多信息

    newSingleThreadExecutor。单线程执行器创建一个 工作线程来处理任务,如果它意外死亡则替换它。 任务保证按照顺序依次处理 任务队列强加的顺序(FIFO、LIFO、优先顺序)。[4]

    [4] 单线程执行器也提供足够的内部 同步以保证任务所做的任何内存写入都是 对后续任务可见;这意味着对象可以安全地 仅限于“任务线程”,即使该线程可能被替换 不时与另一个人。

    【讨论】:

      【解决方案5】:

      我更喜欢使用ExecutorServiceThreadPoolExecutor,即使是单个数字线程。它们提供了更大的灵活性。

      查看相关 SE 问题中的 ExecutorServiceThreadPoolExecutor 部分:

      java Fork/Join pool, ExecutorService and CountDownLatch

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

      假设您从自己的线程而不是ExecutorService 开始。将来,如果需要支持多线程,ExecutorServiceThreadPoolExecutor 将为您提供更好的控制和灵活性。您可以在以下这些 API 中微调所需的参数数量。

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

      【讨论】:

        【解决方案6】:

        Executors.newSingleThreadExecutor().execute(command) 将重用之前构建的线程,它不会像 new Thread() 那样创建新线程。如果 60 秒未使用的线程被终止,它是一种包含单个线程的池,其等效为 newFixedThreadPool(1)。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-12-20
          • 2011-06-10
          • 2023-03-30
          • 2012-12-18
          相关资源
          最近更新 更多