Почему два потока Java (в некоторых случаях) более чем в два раза быстрее одного?

StackOverflow https://stackoverflow.com/questions/1447261

Вопрос

Файл: 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

или что-то очень близкое.

Почему такая разница? Почему разделение его на два потока происходит более чем в два раза быстрее, чем простой запуск?

Это было полезно?

Решение

На самом деле вы вообще не ждете окончания потоков.

После того, как вы запустите поток, вы должны затем вызвать .join (), чтобы дождаться его завершения. Здесь происходит то, что все ваши потоки запускаются, и как только запускается последний, вы синхронизируете его, а затем вычисляете время остановки. Это означает, что ваши потоки все еще работают в фоновом режиме.

Изменить. Причина, по которой первый процесс занимает так много времени, заключается в том, что вы делаете серию синхронных вызовов, создавая поток и запуская его, порождая асинхронную задачу.

Редактировать 2: Вот диаграмма последовательности салфеток того, что происходит в вашем первом тесте: http://www.websequencediagrams.com/cgi-bin / cdraw LZ = TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQAYEgABWAABWAABgTFlMQo & амп;? s = салфетку

Вот диаграмма последовательности салфеток того, что происходит во втором тесте: http://www.websequencediagrams.com/cgi-bin/cdraw?lz = TWFpbi0tPkFub255bW91cyBUaHJlYWQ6IFN0YXJ0IEV4YW1wbGUxLnRhc2soKQoACSYyAAEuAAFdAAGBOwCCPjoAgyIGPk1haW46ICJIb3cgbG9uZyBkaWQgdGhhdCB0YWtlPyIKAINmEC0AKwhUYXNrcyBiZWdpbiB0byBmaW5pc2guLi4gKHNvbWUgbWF5IGhhdmUgZW5kZWQgZWFybGllcikK & амп; s = салфетку

Редактировать 3: Я только что понял, что вторая диаграмма последовательности указывает все стрелки на / same / нить. Они на самом деле разные темы, каждый вызов.

Другие советы

Вызов start () в потоке немедленно возвращается, потому что он просто ставит в очередь поток. Сам поток начнет работать в фоновом режиме через некоторое время.

Вот что я получу, добавив соединение с потоками в ваш код:

  

Время выполнения для одного потока: 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 (), потому что другие потоки не блокируются. Если поток завершил свою работу перед вызовом присоединения, вы просто переходите к следующему потоку.

Кроме того, что означает ваш последний комментарий?

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top