简体   繁体   English

Java:使用 ExecutorService 进行并发

[英]Java: Using ExecutorService for concurrency

I want to execute some tasks parallel so I was searching for multithreading in Java and I found this class, ExecutorService.我想并行执行一些任务,所以我在 Java 中搜索多线程,我找到了这个类,ExecutorService。 I tried with simple example but I am not sure whether it is running in parallel.我尝试了一个简单的例子,但我不确定它是否并行运行。

long startTime = System.currentTimeMillis();
List<Callable<String>> callables = new ArrayList<Callable<String>>();
ExecutorService executor = Executors.newCachedThreadPool();
callables.add(new Callable<String>() {
        public String call() {
            for (int i=0; i<100000; i++) {
                System.out.println("i "+i);
            }
            return "Task 1";
        }
    }
);
        
callables.add(new Callable<String>() {
        public String call() {
            for (int j=0; j<100000; j++) {
                System.out.println("j "+j);
            }
            return "Task 2";
        }
    }
);
        
callables.add(new Callable<String>() {
     public String call() {
          for (int k=0; k<100000; k++) {
              System.out.println("k "+k);
          } 
          return "Task 3";
      }
  }
);
try {
    List<Future<String>> futureLst = executor.invokeAll(callables);
    for (Future future : futureLst) {
        try {
            System.out.println(future.get());
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
executor.shutdown();
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));

The above code works fine as expected and prints the count and returns the string.上面的代码按预期工作正常并打印计数并返回字符串。 The time taken for the above program to execute is "3229" milliseconds.上述程序执行所需的时间为“3229”毫秒。

I rewrote the above program as below,我把上面的程序改写如下,

long startTime = System.currentTimeMillis();
for (int i=0; i<100000; i++) {
    System.out.println("i "+i);
}
for (int j=0; j<100000; j++) {
    System.out.println("j "+j);
}
for (int k=0; k<100000; k++) {
    System.out.println("k "+k);
}
System.out.println("Time Taken - "+ (System.currentTimeMillis() - startTime));

The time taken for this program is "3104" milliseconds which is lesser than the one coded with executing parallel.这个程序花费的时间是“3104”毫秒,比并行执行编码的时间少。

So am I doing anything wrong in first program ?那么我在第一个程序中做错了什么吗? Is my first program running tasks in parallel, since I see without thread is taking less time?我的第一个程序是否并行运行任务,因为我看到没有线程花费的时间更少?

First one is sequential, second one is parallel -- that's fine.第一个是顺序的,第二个是并行的——这很好。

It looks like the running time consists mainly of slow console write operations inside System.out.println call (see Why is System.out.println so slow? ).看起来运行时间主要由System.out.println调用中缓慢的控制台写入操作组成(请参阅为什么 System.out.println 这么慢? )。

You should observe different behavior (and parallel version speedup) if you write to a file instead.如果您改为写入文件,您应该观察不同的行为(和并行版本加速)。

What your tasks mostly do is writing into standard output using the System.out.println call which is PrintStream.println method.您的任务主要是使用System.out.println调用(即PrintStream.println方法)写入标准输出。 It eventually calls PrintStream.write method which body is synchronized.它最终调用PrintStream.write方法,其中主体已同步。 Thus you just waste time on creating threads and synchronization overheads.因此,您只是将时间浪费在创建线程和同步开销上。 As PrintStream is sequential by nature, it cannot output in parallel, so when single stream is writing, others just waiting for it.由于PrintStream本质上是顺序的,它不能并行输出,所以当单个流正在写入时,其他人只是在等待它。 Some operations can be parallelized like your for loop and concatenation of string and number, but they are much faster than the output to stdout.某些操作可以像 for 循环和字符串和数字的连接一样并行化,但它们比输出到 stdout 快得多。

To gain the additional performance from the concurrency you should avoid using the shared sequential resource.为了从并发中获得额外的性能,您应该避免使用共享的顺序资源。 In your case it's standard output stream.在您的情况下,它是标准输出流。

Your code is correct.你的代码是正确的。 The result is due to the computation is too simple and run too fast.结果是由于计算太简单,运行速度太快。 Most of the run time is decided by the speed of console output so the benefit of multi-threading can not make up for the overhead of setting up & shutting down the thread pool.大部分运行时间由控制台输出的速度决定,因此多线程的好处并不能弥补设置和关闭线程池的开销。 Also, the try-catch setup also adds a small overhead (very small, but enough to tangle the result in this simple scenario).此外,try-catch 设置还增加了一个小的开销(非常小,但足以在这个简单的场景中纠结结果)。 --> You could try to increase the loop size (hint: use a static variable MAX_LOOP for faster testing) and you will see the different. --> 您可以尝试增加循环大小(提示:使用静态变量 MAX_LOOP 进行更快的测试),您将看到不同之处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM