为什么两个Java线程(在某些情况下)的速度是一个的两倍?

时间:2009-09-18 23:56:33

标签: java multithreading benchmarking

文件:Example1.java

public class Example1 implements Runnable {

    public void run() {
        for(int i = 0; i < 100000000; i++) {
            int x = 5;
            x = x * 4;
            x = x % 3;
            x = x + 9000;
            x = x * 923;
        }
    }

    public static void task() {
        for(int i = 0; i < 100000000; i++) {
            int x = 5;
            x = x * 4;
            x = x % 3;
            x = x + 9000;
            x = x * 923;
        }
        for(int i = 0; i < 100000000; i++) {
            int x = 9;
            x = x * 2;
            x = x % 4;
            x = x + 3241;
            x = x * 472;
        }
    }

    public static void main(String[] args) {

        long startTime = System.currentTimeMillis();
            Example1.task();
            Example1.task();
            Example1.task();
            Example1.task();
            Example1.task();
        long stopTime = System.currentTimeMillis();
        long runTime = stopTime - startTime;
        System.out.println("Run time for one thread: " + runTime);


        startTime = System.Example1();
            (new Thread(new Example1())).start();
            (new Thread(new Example2())).start();
            (new Thread(new Example1())).start();
            (new Thread(new Example2())).start();
            (new Thread(new Example1())).start();
            (new Thread(new Example2())).start();
            (new Thread(new Example1())).start();
            (new Thread(new Example2())).start();
            (new Thread(new Example1())).start();
            (new Thread(new Example2())).start();
        stopTime = System.currentTimeMillis();
        runTime = stopTime - startTime;
        System.out.println("Run time for two threads: " + runTime);


    }

}

文件:Example2.java

public class Example2 implements Runnable {

    public void run() {
        for(int i = 0; i < 100000000; i++) {
            int x = 9;
            x = x * 2;
            x = x % 4;
            x = x + 3241;
            x = x * 472;
        }        
    }
}

当我运行它时,它输出:

  

一个线程的运行时间:1219

     

两个线程的运行时间:281

或非常接近的东西。

为什么会有这样的差异?为什么将它分成两个线程比直接运行它快两倍?

3 个答案:

答案 0 :(得分:19)

你实际上并没有等待线程完成。

启动线程后,必须在其上调用.join()以等待它完成。这里发生的是你的所有线程都在启动,一旦最后一个线程启动,你计时它然后计算停止时间。这意味着您的线程仍在后台运行。

编辑:第一个花费这么长时间的原因是因为你正在进行一系列同步调用,而创建一个线程并启动它会产生一个异步任务。

编辑2:这是第一次测试中发生的情况的餐巾序列图: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQAYEgABWAABWAABgTFlMQo&s=napkin

这是第二次测试中发生的情况的餐巾序列图: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=TWFpbi0tPkFub255bW91cyBUaHJlYWQ6IFN0YXJ0IEV4YW1wbGUxLnRhc2soKQoACSYyAAEuAAFdAAGBOwCCPjoAgyIGPk1haW46ICJIb3cgbG9uZyBkaWQgdGhhdCB0YWtlPyIKAINmEC0AKwhUYXNrcyBiZWdpbiB0byBmaW5pc2guLi4gKHNvbWUgbWF5IGhhdmUgZW5kZWQgZWFybGllcikK&s=napkin

编辑3:我刚刚意识到第二个序列图将所有箭头指向/ same / thread。它们实际上是不同的线程,每次调用。

答案 1 :(得分:2)

Thread上的call start()会立即返回,因为它只是将线程排入队列。 一段时间后,线程本身将开始在后台运行。

答案 2 :(得分:1)

以下是我的代码添加到线程的连接:

  

一个线程的运行时间:566

     

两个线程的运行时间:294

所以以前的答案都是正确的。

编辑:我以这种方式添加了连接。你可以做得更好,但没关系:

    Thread[] t = new Thread[10];
    (t[0] = new Thread(new Example1())).start();
    (t[1] = new Thread(new Example2())).start();
    (t[2] = new Thread(new Example1())).start();
    (t[3] = new Thread(new Example2())).start();
    (t[4] = new Thread(new Example1())).start();
    (t[5] = new Thread(new Example2())).start();
    (t[6] = new Thread(new Example1())).start();
    (t[7] = new Thread(new Example2())).start();
    (t[8] = new Thread(new Example1())).start();
    (t[9] = new Thread(new Example2())).start();

    for (Thread t1: t) {
        try {
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

您必须加入每个帖子。但是,您不会在join()中浪费您的时间,因为其他线程未被阻止。如果线程在您调用join之前已经完成了它的执行,那么您只需继续下一个线程。

另外,你的上一条评论是什么意思?