Pourquoi deux threads Java (dans certains cas) sont-ils plus de deux fois plus rapides qu'un?

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

Question

Fichier: 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);


    }

}

Fichier: 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;
        }        
    }
}

Lorsque je lance ceci, il génère:

  

Durée d'exécution pour un thread: 1219

     

Durée d'exécution pour deux threads: 281

ou quelque chose de très proche.

Pourquoi y a-t-il une telle différence? Pourquoi le scinder en deux threads va-t-il plus de deux fois plus vite que de le lancer directement?

Était-ce utile?

La solution

En fait, vous n'attendez pas que les discussions se terminent.

Une fois que vous avez démarré un fil de discussion, vous devez ensuite appeler .join () dessus pour attendre son achèvement. Ce qui se passe ici, c’est que tous vos threads commencent et dès que le dernier a commencé, vous le chronométrez et vous calculez l’heure de fin. Cela signifie que vos threads fonctionnent toujours en arrière-plan.

Éditer: la première raison est si longue parce que vous effectuez une série d'appels synchrones lorsque vous créez un thread et que vous le démarrez, ce qui génère une tâche asynchrone.

Éditer 2: Voici un diagramme de séquence de serviettes illustrant ce qui se passe lors de votre premier test: http://www.websequencediagrams.com/cgi-bin / cdraw? lz = TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQkQQEQAEFABHABO & F;

Voici un diagramme de séquence de serviettes illustrant ce qui se passe dans votre deuxième test: http://www.websequencediagrams.com/cgi-bin/cdraw?lz = TWFpbi0tPkFub255bW91cyBUaHJlYWQ6IFN0YXJ0IEV4YW1wbGUxLnRhc2soKQoACSYyAAEuAAFdAAGBOwCCPjoAgyIGPk1haW46ICJIb3cgbG9uZyBkaWQgdGhhdCB0YWtlPyIKAINmEC0AKwhUYXNrcyBiZWdpbiB0byBmaW5pc2guLi4gKHNvbWUgbWF5IGhhdmUgZW5kZWQgZWFybGllcikK & amp; s = serviette

Éditer 3: Je viens de me rendre compte que le deuxième diagramme de séquence pointe toutes les flèches vers le / même / fil. Ce sont en fait différents threads, chaque appel.

Autres conseils

L'appel start () sur un thread est renvoyé immédiatement car il met simplement en file d'attente le thread. Le fil lui-même commencera à s’exécuter en arrière-plan un peu plus tard.

Voici ce que j'obtiens avec votre code en ajoutant join aux discussions:

  

Durée d'exécution pour un thread: 566

     

Durée d'exécution pour deux threads: 294

Les réponses précédentes sont donc correctes.

EDIT: J'ai ajouté des jointures de cette façon. Vous pouvez le faire mieux, mais peu importe:

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

Vous devez rejoindre chaque fil de discussion. Cependant, vous ne perdez pas votre temps à attendre dans join () car les autres threads ne sont pas bloqués. Si le thread a terminé son exécution avant que vous appeliez à rejoindre le groupe, continuez simplement au prochain thread.

De plus, que signifie votre dernier commentaire?

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top