Java:使用 ExecutorService 实现并发

标签 java multithreading parallel-processing

我想并行执行一些任务,因此我在 Java 中搜索多线程,并找到了这个类 ExecutorService。我尝试了简单的示例,但我不确定它是否并行运行。

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));

上面的代码按预期工作正常,打印计数并返回字符串。上述程序的执行时间为“3229”毫秒。

我将上面的程序重写如下,

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));

该程序花费的时间为“3104”毫秒,比并行执行编码的时间要短。

那么我在第一个程序中做错了什么吗?我的第一个程序是否并行运行任务,因为我看到没有线程花费的时间更少?

最佳答案

您的任务主要做的是使用 System.out.println 调用(即 PrintStream.println 方法)写入标准输出。它最终调用 PrintStream.write同步主体的方法。因此,您只是将时间浪费在创建线程和同步开销上。由于PrintStream本质上是顺序的,它不能并行输出,所以当单个流正在写入时,其他流只是在等待它。有些操作可以并行化,例如 for 循环以及字符串和数字的串联,但它们比输出到 stdout 快得多。

要从并发中获得额外的性能,您应该避免使用共享顺序资源。在您的情况下,它是标准输出流。

关于Java:使用 ExecutorService 实现并发,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31760410/

相关文章:

c++ - openmp 并行部分基准

java - Spring Data JPA规范,如何在唯一的sql请求中获取@JoinColumn数据

java - 如何在 java 8 中使用带有 null 和空检查的平面图合并多个列表?

java - 使用 "import static"有什么好处?

c - 基准测试、顺序 x 并行程序。亚线性加速?

c - 如何使用 MPI_Gather 函数从变量中获取数据

c - 在 c 中使用 p 线程编写并行快速排序

java - 如何使用java配置@CosmosDBtrigger?

python - Python 线程是否打印到与主线程不同的缓冲区?

iphone - Objective C - 多线程问题