Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 当我在一台四核机器上使用多个线程时,为什么这段代码没有看到任何显著的性能提升?_Java_Multithreading_Concurrency_Executor - Fatal编程技术网

Java 当我在一台四核机器上使用多个线程时,为什么这段代码没有看到任何显著的性能提升?

Java 当我在一台四核机器上使用多个线程时,为什么这段代码没有看到任何显著的性能提升?,java,multithreading,concurrency,executor,Java,Multithreading,Concurrency,Executor,我编写了一些Java代码来了解更多关于Executor框架的信息 具体地说,我编写代码是为了验证-这意味着如果对任何整数迭代应用以下函数,最终得到1: f(n)=((n%2)==0)?n/2:3*n+1 CH还未被证实,我认为这是了解Executor的一个好方法。为每个线程分配一个整数范围[l,u]以进行检查 具体来说,我的程序有3个参数-N(我要检查CH的数字)、RANGESIZE(线程必须处理的间隔长度)和NTHREAD(线程池的大小) 我的代码运行得很好,但我看到的加速比我预期的要小得多—

我编写了一些Java代码来了解更多关于Executor框架的信息

具体地说,我编写代码是为了验证-这意味着如果对任何整数迭代应用以下函数,最终得到1:

f(n)=((n%2)==0)?n/2:3*n+1

CH还未被证实,我认为这是了解Executor的一个好方法。为每个线程分配一个整数范围[l,u]以进行检查

具体来说,我的程序有3个参数-N(我要检查CH的数字)、RANGESIZE(线程必须处理的间隔长度)和NTHREAD(线程池的大小)

我的代码运行得很好,但我看到的加速比我预期的要小得多——从1个线程到4个线程时,加速率大约为30%

我的逻辑是,计算完全受CPU限制,每个子任务(检查CH是否有固定大小范围)所用的时间大致相同

有人知道为什么我没有看到3到4倍的速度提升吗

如果您可以在增加线程数(以及机器、JVM和操作系统)时报告运行时,那也将非常好

细节

运行时:

java-d64-server-cp。Collatz 10000000 1000000 4=>4个线程,耗时28412毫秒

java-d64-server-cp。Collatz 10000000 1000000 1=>1个线程,需要38286毫秒

处理器:

2.4GHZ、4GB的英特尔Q6600四核处理器。机器卸了货

爪哇:

java版本“1.6.0_15” Java(TM)SE运行时环境(build 1.6.0_15-b03) Java HotSpot(TM)64位服务器虚拟机(构建14.1-b02,混合模式)

操作系统:

Linux quad0 2.6.26-2-amd64#1 SMP星期二3月9日22:29:32 UTC 2010 x86_64 GNU/Linux

代码:(我无法获得要发布的代码,我认为它太长了,无法满足需求,源代码可以在

import java.math.biginger;
导入java.util.Date;
导入java.util.List;
导入java.util.ArrayList;
导入java.util.concurrent.ExecutorService;
导入java.util.concurrent.Executors;
类MyRunnable实现Runnable{
公共int较低;
公共int上;
MyRunnable(整数下限,整数上限){
this.lower=更低;
this.upper=upper;
}
@凌驾
公开募捐{
对于(int i=较低;i=1){
N=整数.parseInt(args[0]);
}
如果(args.length>=2){
RANGESIZE=Integer.parseInt(args[1]);
}
如果(参数长度>=3){
NTHREADS=Integer.parseInt(args[2]);
}
}
公共静态void maintest(字符串[]args){
System.out.println(“检查(1):”+检查(1));
System.out.println(“检查(3):”+检查(3));
System.out.println(“检查(8):”+检查(8));
parseArgs(args);
}
公共静态void main(字符串[]args){
long lDateTime=new Date().getTime();
parseArgs(args);
List threads=new ArrayList();
ExecutorService executor=Executors.newFixedThreadPool(n线程);
对于(int i=0;i<(N/RANGESIZE);i++){
Runnable worker=新的MyRunnable(i*RANGESIZE+1,(i+1)*RANGESIZE);
执行人,执行人(工人);
}
executor.shutdown();
而(!executor.isTerminated()){
}
System.out.println(“完成所有线程”);
long fDateTime=new Date().getTime();
System.out.println(“检查到“+N+”的时间(毫秒)为”+
(fDateTime-lDateTime)+
“(“+N/(fDateTime-lDateTime)+”每毫秒)”;
}
}

忙碌的等待可能是一个问题:

while (!executor.isTerminated() ) { 
} 
您可以改为使用
waittermination()

while (!executor.awaitTermination(1, TimeUnit.SECONDS)) {}

您使用的是BigInteger。它会占用大量寄存器空间。在编译器级别,最可能出现的是寄存器溢出,这会使进程内存受到限制

还要注意的是,在对结果计时时,没有考虑JVM分配线程和使用线程池所花费的额外时间

当您使用常量字符串时,也可能会出现内存冲突。所有字符串都存储在共享字符串池中,因此它可能会成为一个瓶颈,除非java对此非常聪明


总的来说,我不建议使用Java来处理这类事情。使用pthreads对您来说是一种更好的方式。

您可以尝试使用submit函数,然后观察将来返回的线程,检查线程是否已完成

在关闭之前,Terminate不会返回

未来提交(可运行任务) 提交可运行任务以执行,并返回表示该任务的Future

已删除() 如果关闭后所有任务都已完成,则返回true

试试这个

public static void main(String[] args) {
    long lDateTime = new Date().getTime();
    parseArgs(args);
    List<Thread> threads = new ArrayList<Thread>();
    List<Future> futures = new ArrayList<Future>();

    ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
    for (int i = 0; i < (N / RANGESIZE); i++) {
        Runnable worker = new MyRunnable(i * RANGESIZE + 1, (i + 1) * RANGESIZE);
        futures.add(executor.submit(worker));
    }
    boolean done = false;
    while (!done) {
        for(Future future : futures) {
            done = true;
            if( !future.isDone() ) {
                done = false;
                break;
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    System.out.println("Finished all threads");
    long fDateTime = new Date().getTime();
    System.out.println("time in milliseconds for checking to " + N + " is " +
            (fDateTime - lDateTime) +
            " (" + N / (fDateTime - lDateTime) + " per ms)");
    System.exit(0);
}
publicstaticvoidmain(字符串[]args){
long lDateTime=new Date().getTime();
parseArgs(args);
List threads=new ArrayList();
列表期货=新的ArrayList();
ExecutorService executor=Executors.newFixedThreadPool(n线程);
对于(int i=0;i<(N/RANGESIZE);i++){
Runnable worker=新的MyRunnable(i*RANGESIZE+1,(i+1)*RANGESIZE);
期货.add(执行者.submit(工作者));
}
布尔完成=假;
而(!完成){
for(未来:未来){
完成=正确;
如果(!future.isDone()){
完成=错误;
打破
}
}
试一试{
睡眠(100);
}捕捉(中断异常e){
e、 printStackTrace();
}
}
System.out.println(“完成所有线程”);
long fDateTime=new Date().getTime();
System.out.println(“检查到“+N+”的时间以毫秒为单位”+
(fDateTime-lDateTime)+
“(“+N/(fDateTime-lDateTime)+”每毫秒)”;
系统出口(0);
}

正如@axtavt所回答的,繁忙的等待可能是一个问题。您应该首先解决这个问题,因为它是ans的一部分
public static void main(String[] args) {
    long lDateTime = new Date().getTime();
    parseArgs(args);
    List<Thread> threads = new ArrayList<Thread>();
    List<Future> futures = new ArrayList<Future>();

    ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
    for (int i = 0; i < (N / RANGESIZE); i++) {
        Runnable worker = new MyRunnable(i * RANGESIZE + 1, (i + 1) * RANGESIZE);
        futures.add(executor.submit(worker));
    }
    boolean done = false;
    while (!done) {
        for(Future future : futures) {
            done = true;
            if( !future.isDone() ) {
                done = false;
                break;
            }
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    System.out.println("Finished all threads");
    long fDateTime = new Date().getTime();
    System.out.println("time in milliseconds for checking to " + N + " is " +
            (fDateTime - lDateTime) +
            " (" + N / (fDateTime - lDateTime) + " per ms)");
    System.exit(0);
}