【发布时间】:2016-09-25 07:41:50
【问题描述】:
======================= 编辑 2016 05 27 16:55 已解决 ================= ======
这个问题解决了!感谢@Paul Hankin,你是对的! Java擅长做“for() {i = i + 1}”,所以当我把代码改成“for() {i = i + i}”时,java就输了。
(PS:使用Java ExecutorService确实让java的结果很好,但还是不如goroutine,这里没有ExecutorService例子)
Java 代码:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String args[]) throws InterruptedException {
List<Thread> threads = new ArrayList<Thread>();
for(int i = 0; i < 10; i ++) {
threads.add(new Thread(new RunableAdd()));
}
long timeStart = System.currentTimeMillis();
for(Thread t: threads) {
t.start();
}
for(Thread t: threads) {
t.join();
}
System.out.println("Time Use : " + (System.currentTimeMillis() - timeStart) + "ms");
}
}
class RunableAdd implements Runnable {
@Override
public void run() {
long i = 1;
while(true) {
i += i;
if (i > 1000 * 1000* 1000) {
return;
}
}
}
}
Golang 代码:
package main
import (
"fmt"
"time"
)
func main() {
chanSignal := make(chan bool)
startTime := time.Now()
goroutineNum := 10
for i := 0; i < goroutineNum; i++ {
go func() {
j := 1
for {
j = j + j
if j > 1000*1000*1000 {
chanSignal <- true
return
}
}
}()
}
for i := 0; i < goroutineNum; i++ {
<-chanSignal
}
fmt.Println(time.Since(startTime))
}
结果:
线程/goroutine 数量:10
java : Time Use : 4ms
golang : 19.105µs
线程/goroutine 数量:100
java : Time Use : 27ms
golang : 180.272µs
线程/goroutine 数量:1000
java: Time Use : 512ms
golang : 1.565521ms
原来golang好,java好“i = i + 1”,
有趣的是,当goroutine num加10时,时间成本不到10倍。
================================结束=============== ======================
我今天用java线程测试golang goroutine,我认为golang goroutine应该比java线程快,但是我的测试结果显示java线程获胜。
环境: 爪哇 1.8 golang 1.6
cpu 是四核
$ cat /proc/cpuinfo | grep 'core id'
core id : 0
core id : 0
core id : 1
core id : 1
Java 代码:
import java.util.ArrayList;
import java.util.List;
public class Test {
public static void main(String args[]) throws InterruptedException {
List<Thread> threads = new ArrayList<Thread>();
for(int i = 0; i < 100; i ++) {
threads.add(new Thread(new RunableAdd()));
}
long timeStart = System.currentTimeMillis();
for(Thread t: threads) {
t.start();
}
for(Thread t: threads) {
t.join();
}
System.out.println("Time Use : " + (System.currentTimeMillis() - timeStart) + "ms");
}
}
class RunableAdd implements Runnable {
@Override
public void run() {
int i = 0;
while(true) {
i ++;
if (i == 10 * 1000* 1000) {
return;
}
}
}
}
golang 代码:
package main
import (
"fmt"
"time"
)
func main() {
chanSignal := make(chan bool)
startTime := time.Now()
goroutineNum := 100
for i := 0; i < goroutineNum; i++ {
go func() {
j := 0
for {
if j == 10*1000*1000 {
chanSignal <- true
return
} else {
j = j + 1
}
}
}()
}
for i := 0; i < goroutineNum; i++ {
<-chanSignal
}
fmt.Println(time.Since(startTime))
}
结果是:
当我设置线程数 10 时:
Java : Time Use : 18ms
golang : 50.952259ms
线程数 100:
Java : Time Use : 88ms
golang : Time Use : 458.239685ms
线程数 1000:
Java : Time Use : 1452ms
golang : 4.701811465s
Java Thread 真的比 golang goroutine 快吗?还是我的程序做错了什么?
【问题讨论】:
-
“我认为 golang goroutine 应该比 java 更快” -- 你为什么这么认为?
-
@JimGarrison accrouding to The Go scheduler this page 似乎每个人都说goroutine更轻,创建速度比线程快,成本低于线程,并且当在一个cpu上执行大量线程时,改变cpu成本线程,但是将一个 goroutine 更改为另一个 goroutine 几乎没有任何成本。
-
@Alexniver 没错。您的代码是否证明了这一点?您的代码是否允许 Go 调度程序运行?两个代码的所有同步点是否相同?您的代码是否衡量了更改线程/goroutines 的成本?
-
在使用空循环和未使用的变量进行基准测试时要小心,现在的编译器倾向于对此进行优化。
-
请使用
System.nanoTime(),因为currentTimeMillis()不精确,因为the granularity of the value depends on the underlying operating system and may be larger。
标签: java multithreading go goroutine