【问题标题】:Java Callable : Time taken more than a single thread processJava Callable : 比单个线程进程花费的时间
【发布时间】:2015-08-05 19:20:00
【问题描述】:

我有以下示例代码。

import java.util.*;
import java.lang.*;
import java.io.*;

import java.util.concurrent.*;
public class CalculationThread implements Callable<Long> {

    public Long call() throws Exception {
        long k=0L;
        for(int i=0;i<100000;i++){
            for(int j=0;j<50;j++){
                k=i+j;
            }
        }
        return k;
    }
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executorService = Executors.newFixedThreadPool(4);
        long startTime = System.nanoTime();
        for(int lo=0;lo<5000;lo++){
            Future<Long> result = executorService.submit(new CalculationThread());

            try {
                Long l = result.get();
            } catch (Exception e) {
                result.cancel(true);
            }

        }
        long endTime = System.nanoTime();
        System.out.println("Using threads took "+(endTime - startTime) + " ns");

        executorService.shutdown();
        executorService.awaitTermination(1, TimeUnit.SECONDS);

        long k=0L;
        startTime = System.nanoTime();
        for(int lo=0;lo<5000;lo++){
            for(int i=0;i<100000;i++){
                for(int j=0;j<50;j++){
                    k=i+j;
                }
            }

        }
        endTime = System.nanoTime();
        System.out.println("Generally it takes "+(endTime - startTime) + " ns");

    }
}

输出和

一样分散
Using threads took 101960490 ns
Generally it takes 143107865 ns

Using threads took 245339720 ns
Generally it takes 149699885 ns

正如人们注意到的那样,第二行几乎是不变的,而线程版本变化很大。为什么会出现这种情况?可以做些什么来减少变异性?请让我知道我是否在做一些愚蠢的事情,因为我是 Java 多线程的新手。

【问题讨论】:

  • 您将 4 个初始线程添加到可用的 4 个线程中,并将剩余的 4996 个操作添加到线程池中,这与较短的总执行时间相比效率并不高~149 ms (General execution) .线程在time &gt; 2 s min 中将非常有用,并尝试减少线程池中的队列数。

标签: java multithreading callable java-threads


【解决方案1】:

Future#get 阻塞,直到您的可调用对象完成。所以主线程向池提交一个 Callable,然后等待它完成,然后再提交下一个。您有创建池的四个线程的开销,然后您在线程和创建可调用对象的对象创建之间进行上下文切换(在可调用对象被丢弃时进行垃圾收集),然后您什么都不做工作同时进行。

您如何获得使用池的版本更快的数字令人费解。当我在本地运行它时(并且很好地制作了一个 MVCE,顺便说一句,我可以复制和粘贴而不做任何更改并且它可以工作)我得到线程池部分的数字始终更高,它需要大约 3 倍的时间单-线程代码。

【讨论】:

  • 感谢您的回复。我不确定我到底发生了什么。我理解您在可调用完成之前获取块的观点。您能否提供一个示例/链接来说明如何处理这种情况,我可以看到实际时间减少?
  • @SandipanBhattacharyya:那得晚点,现在做不到。您可以使用 runnables 而不是等待输出。或使用完成服务并在您全部提交后接受任务。
  • 一定会尝试的。感谢您的帮助!
猜你喜欢
  • 2020-12-10
  • 1970-01-01
  • 2019-08-24
  • 2014-04-23
  • 1970-01-01
  • 2021-09-01
  • 2014-02-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多