为什么是两个Java线程(在某些情况下),比快两倍多一个?
-
22-07-2019 - |
题
文件: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
或极为类似。
为什么会出现这样的差异?为什么拆分为两个线程去两次以上的不仅仅是直接运行速度更快?
解决方案
你实际上没有等待的线程在所有完成。
一旦你启动一个线程,则必须调用。加入()就可以等待它完成。这里发生的事情是,所有的线程开始,一旦最后一个开始,你的时钟,然后计算出的停止时间。这意味着,你的线程仍然在后台运行。
编辑:为什么第一个需要很长时间的原因是因为你正在做一系列的同步调用,而创建一个线程并启动它产生异步任务
编辑2:这是在你的第一次测试会发生什么餐巾纸序列图: http://www.websequencediagrams.com/cgi-bin / cdraw?LZ = TWFpbi0-RXhhbXBsZTE6IFRhc2sgc3RhcnRlZAphY3RpdmF0ZSAAGAgKACEILS0-TWFpbjogZG9uZQpkZQAYEgABWAABWAABgTFlMQo&S =餐巾
修改3:我只是意识到的是,第二序列图点的所有箭头到/同/线程的。它们实际上是不同的线程,每个呼叫。
其他提示
在调用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()方法,因为其他线程没有被阻塞。如果线程完成它的executution你打电话之前加入,你只是继续下一个主题。
此外,什么是你最后的评论是什么意思?