【问题标题】:What happens if a Runnable executed several times in an ExecutorService如果 Runnable 在 ExecutorService 中执行多次会发生什么
【发布时间】:2015-07-17 06:54:51
【问题描述】:

如果一个线程在同一时间多次执行会发生什么。假设我有类似的线程

private Runnable mySampleThread() {
    return new Runnable() {
        @Override
        public void run() {
        //something is going on here.

        }
    };
}

我创建了一个固定线程池为 10 的ExecutorService。如果我在这个ExecutorService 中执行mySampleThread 10 次会发生什么。 像下面这样,

ExecutorService mySampleExecutor = Executors.newFixedThreadPool(10);
while (i <= 10) {
    mySampleExecutor.execute(mySampleThread);
    i++;
}

【问题讨论】:

  • 你试过了吗?怎么了?先试试吧
  • Runnable 不是Thread。它只是一个带有一种方法的普通 Java 对象。所发生的只是这个方法被执行了不止一次。
  • “如果 .. 会发生什么”有点宽泛。缩小范围。提及您期望什么,您不期望什么以及实际发生的事情(通过首先运行您的代码)。您似乎在暗示从同一个 Runnable 对象产生多个线程的效果。

标签: java multithreading executorservice


【解决方案1】:

答案很简单。 Executor 将执行 Runnable 对象(它不是 Thread 对象),如文档 Interface Executor 中所述

在未来的某个时间执行给定的命令。该命令可以在新线程、池线程或调用线程中执行,由 Executor 实现自行决定。

基本上,Executor 会从它的内部池(ThreadPoolExecutor)中提取一个线程,给它分配一个 runnable 执行 run() 方法。

【讨论】:

    【解决方案2】:

    首先详细说明您的问题或查询。

    尽管如此,假设您正在调用方法“mySampleThread()”而没有丢失括号。这个方法实际上每次都返回一个新的 Runnable 对象,所以你将一个新的 runnable 全部 10 次传递给 executor。这意味着您要向执行者提交 10 个不同的任务。因此,如果 executor 为每个任务创建不同的线程(这取决于它的实现),那么无论你在 run() 中编写什么代码,都将在 10 个不同的线程中执行 10 次。

    如其他答案所述,传递给 executor 的可运行对象不是线程。

    希望它澄清。

    顺便说一下,你可以试试运行程序。

    【讨论】:

      【解决方案3】:

      正如其他答案明确指出的那样,新线程的数量将与调用次数一样多(由于使用过的执行器可能会更少,我专注于Runnable 重用,限制执行器的线程数在其他答案)。所有这些都是用单个 Runnable 对象创建的。

      值得一提的是,我个人多次使用它 - 这是在多个线程之间共享数据的方法之一,因为所有这些线程都共享用于创建的Runnable。此时同步问题开始发挥作用,但这是另一回事。

      这里的代码展示了典型用法和前面提到的同步问题。

      import java.util.concurrent.ExecutorService;
      
      class MyThread implements Runnable {
          public int counter = 0;
      
          @Override
          public void run() {
              for (int i = 0; i < 10000; i++) {
                  counter++;
              }
          }
      }
      
      class MySynchronizedThread implements Runnable {
          public int counter = 0;
      
          @Override
          public void run() {
              for (int i = 0; i < 10000; i++) {
                  synchronized (this) {
                      counter++;
                  }
              }
          }
      }
      
      public class RunnableTest {
      
          public static void main(String[] args) throws InterruptedException {
      
              MyThread runnableObject = new MyThread();
              ExecutorService ex = Executors.newFixedThreadPool(5);
              for (int i = 0; i < 5; i++) {
                  ex.execute(runnableObject);
              }
      
      
              ex.shutdown();
              ex.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
      
              System.out
                      .println("Without synchronization: " + runnableObject.counter);
      
              MyThread runnableSynchronizedObject = new MyThread();
              ExecutorService ex2 = Executors.newFixedThreadPool(5);
              for (int i = 0; i < 5; i++) {
                  ex2.execute(runnableSynchronizedObject);
              }
      
              ex2.shutdown();
              ex2.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);
              System.out.println("Without synchronization: "
                      + runnableSynchronizedObject.counter);
      
          }
      }
      

      【讨论】:

      • 新线程的数量与调用的数量一样多。不。使用执行器服务的全部意义在于创建一个每个新任务的新线程。
      • @jameslarge 我不认为这是全部点。同样,对于 OP 示例和我的示例,此语句都是正确的,所以是的,线程数与执行数一样多。
      • @zubergu 您的示例确实解释了同步,但是,我认为它与问题无关。您将相同的对象传递给执行程序,这就是您需要处理并发性。
      • 好吧,但那是因为您的示例在两个不同的地方使用了文字 5(OP 的示例使用 10)。如果您将循环计数器更改为 5000,但仍将线程池的大小保留为 5,则它永远不会创建超过 5 个线程。
      • @RahulWinner 我不能同意这种说法。正如明确提到的,这就是为什么有人想要重用 Runnable 对象的例子。显然 OP 是新手,所以我决定包括他在走这条路时会遇到的最典型的问题,从而防止很快看到关于该问题的另一个问题。
      【解决方案4】:

      mySampleExecutor.execute(mySampleThread);mySampleThread 方法没有区别,返回一个新的Runnable object.,每个线程都有自己的Frames

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-04-04
        • 1970-01-01
        • 1970-01-01
        • 2010-12-02
        • 2012-06-16
        • 1970-01-01
        相关资源
        最近更新 更多