启动多个 ExecutorService Java

Launch multiple ExecutorService Java

我想同时启动两个ExecutorService。

比如我的主要是:

MyClass.firstAsync();
MyClass.secondAsync();

并且,

public void firstAsync() {
ExecutorService service = Executors.newFixedThreadPool(4);
    service.submit(new Runnable() {
      public void run() {
            while (true) {
                System.out.println("I m running : First Async");
         }
    });
}

然后

   public void secondAsync() {
    ExecutorService service = Executors.newFixedThreadPool(4);
        service.submit(new Runnable() {
          public void run() {
            while (true) {
               System.out.println("I m running : Second Async");
              }
         });
    }

问题是:当调用第二个 class 时,它取代了第一个。所以我有这个输出:

I m running : First Async

虽然第二个 ExecutorService 没有启动,但我有这个输出

I m running : Second Async

第二个启动时。

我也尝试将它们放在同一个服务上(在同一个 ExecutorService 上有两个 service.submit(...))但它根本不起作用

我想要的是两个输出,在"same time".

谢谢, 克莱门特

您不能指望控制线程的执行。 如果你想模拟它,让我们在你的循环中引入:

Thread.sleep(10); 

这会强制当前 运行 线程休眠,并为其他线程提供执行的机会。

但不要指望编排线程的执行。

您的代码按预期工作。我假设您期望得到这样的输出:

I m running : First Async
I m running : Second Async
I m running : First Async
I m running : Second Async

但是你得到的是:

I m running : First Async
I m running : First Async
...
I m running : First Async 
I m running : Second Async
I m running : Second Async
...
I m running : Second Async
I m running : First Async
...
I m running : First Async
I m running : Second Async
...
I m running : Second Async

也许您从一个线程获得了太多输出,以至于您看不到另一个线程的输出。

发生这种情况是因为两个线程竞争对同一输出流的访问权限 (System.out),并且每次一个线程获得访问权限时,它都会设法在另一个线程获得权限之前打印多行(可能数千行)流。

要对此进行测试,请在循环中添加延迟,这样每个线程都有时间一次只打印一行。

while (true) {
    System.out.println("I m running : First Async");
    Thread.sleep(100);  // <---- and surround with try-catch
}
while (true) {
    System.out.println("I m running : Second Async");
    Thread.sleep(100);  // <---- and surround with try-catch
}

(1) 你的代码没问题(除了下面的一些小评论),问题很简单,实际代码太快了,没有注意到并发!此外,println 通常是同步的。如果您将每个 "run()" 替换为一些打印多行的循环,您会注意到并发性。

(2) 我会考虑两个修复,不管: (a) 你真的需要 2 个独立的线程池吗?这样做也没关系,只是从例子(b)中看不出原因,我觉得把线程池实例化为局部方法变量意义不大,应该放在可以复用的地方+ 监控 + 有时终止。显然,您可能只是为了讨论而简化了代码...

我想发表评论,但显然我需要在 Whosebug 上获得 50 的声誉才能发表评论(合理,但不幸。)。所以我将尝试回答这个问题。

ExecutorService 旨在成为实现 Executor 接口的管理对象,这意味着它可以在其中容纳一个线程池。线程池可用于托管各种 Runnable 线程对象。它们不必是同一类型。

例如,如果您有一个具有特定功能的 Runable class,您可以从 ExecutorService 持有的线程启动它,因为线程是通用的。如果您需要识别特定的线程以便稍后与它们交互,您可以在每个 Runnable 线程类型中使用一个特定的、不可变的标识符 class 字段和一个 getter 方法。或者,如果您愿意,可以在构造线程对象时存储对线程对象的引用。

或者,还可以查找 运行 threads/thread 组及其 ID。你可以在这里看到这个方法:

http://nadeausoftware.com/articles/2008/04/java_tip_how_list_and_find_threads_and_thread_groups#GettingThreadGroups

你的问题的答案是你不需要有两个 ExecutorServices。由于您可以以静态或动态方式调整线程池的大小,并且您的线程池可以托管异构线程对象。

希望对您有所帮助。我希望这是一个充分的答案。

这是我的最终答案。

在我的 firstAsync() 代码中,有一个从未显示在控制台中的 NullPointerException。

我和我服务的一个人花了一个多小时来解决这个问题。是我的错 你的回答都很好,我的问题很愚蠢。

谢谢,克莱门特。