简体   繁体   English

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

[英]Why are two Java threads (in some cases) more than twice as fast as one?

File: Example1.java 文件: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);


    }

}

File: Example2.java 文件: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;
        }        
    }
}

When I run this, It outputs: 当我运行它时,它输出:

Run time for one thread: 1219 一个线程的运行时间:1219

Run time for two threads: 281 两个线程的运行时间:281

or something very close. 或者非常接近的东西。

Why is there such a difference? 为什么会有这样的差异? Why does splitting it into two threads go more than two times faster than just running it directly? 为什么将它分成两个线程比直接运行它快两倍?

You're actually not waiting for the threads to finish at all. 你实际上并没有等待线程完成。

Once you start a thread, you must then call .join() on it to wait for it to complete. 一旦启动一个线程,就必须在其上调用.join()以等待它完成。 What's happening here is that all of your threads are starting and as soon as the last one has started, you clock it and then calculate the stop time. 这里发生的是你的所有线程都在启动,一旦最后一个线程启动,你计时它然后计算停止时间。 This means that your threads are still running in the background. 这意味着您的线程仍在后台运行。

Edit: The reason why the first one takes so long is because you're making a series of synchronous calls, while creating a thread and starting it spawns an asynchronous task. 编辑:第一个需要这么长时间的原因是因为你正在进行一系列同步调用,而创建一个线程并启动它会产生一个异步任务。

Edit 2: Here's a napkin sequence diagram of what happens in your first test: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQAYEgABWAABWAABgTFlMQo&s=napkin 编辑2:这是第一次测试中发生的情况的餐巾序列图: http//www.websequencediagrams.com/cgi-bin/cdraw ?lz = TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQAYEgABWAABWAABgTFlMQo&s=napkin

Here's a napkin sequence diagram of what happens in your second test: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=TWFpbi0tPkFub255bW91cyBUaHJlYWQ6IFN0YXJ0IEV4YW1wbGUxLnRhc2soKQoACSYyAAEuAAFdAAGBOwCCPjoAgyIGPk1haW46ICJIb3cgbG9uZyBkaWQgdGhhdCB0YWtlPyIKAINmEC0AKwhUYXNrcyBiZWdpbiB0byBmaW5pc2guLi4gKHNvbWUgbWF5IGhhdmUgZW5kZWQgZWFybGllcikK&s=napkin 这里是你的第二个测试会发生什么餐巾纸序列图: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=TWFpbi0tPkFub255bW91cyBUaHJlYWQ6IFN0YXJ0IEV4YW1wbGUxLnRhc2soKQoACSYyAAEuAAFdAAGBOwCCPjoAgyIGPk1haW46ICJIb3cgbG9uZyBkaWQgdGhhdCB0YWtlPyIKAINmEC0AKwhUYXNrcyBiZWdpbiB0byBmaW5pc2guLi4gKHNvbWUgbWF5IGhhdmUgZW5kZWQgZWFybGllcikK&s=napkin

Edit 3: I just realized that the second sequence diagram points all of the arrows to the /same/ thread. 编辑3:我刚刚意识到第二个序列图将所有箭头指向/ same / thread。 They are in fact DIFFERENT threads, each call. 它们实际上是不同的线程,每次调用。

The call start() on a Thread immediately returns because it just enqueues the thread. 线程上的调用start()会立即返回,因为它只是将线程排入队列。 The thread itself will begin running in the background some time later. 一段时间后,线程本身将开始在后台运行。

Here is what I get with your code adding join to the threads: 以下是我的代码添加到线程的连接:

Run time for one thread: 566 一个线程的运行时间:566

Run time for two threads: 294 两个线程的运行时间:294

So previous answers are correct. 所以以前的答案是正确的。

EDIT: I added joins this way. 编辑:我添加加入这种方式。 You can do it better, but it doesn't matter: 你可以做得更好,但没关系:

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

You have to join each thread. 你必须加入每个线程。 However, you don't waste your time waiting in join() because other threads are not blocked. 但是,您不会在join()中浪费您的时间,因为其他线程未被阻止。 If the thread has finished it's executution before you call to join, you just continue to next thread. 如果线程在您调用join之前已经完成了它的执行,那么您只需继续下一个线程。

Also, what does your last comment mean? 另外,你的上一条评论是什么意思?

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

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