Go语言以高并发闻名于世,牛皮不能光靠吹,今天我们就来做一个对比试验,体会一下Go在并发方面的巨大优势!靶子就瞄准Java,谁让它是后端开发语言的老大哥呢。
基本任务:初始化一个100*100的矩阵,矩阵每个元素是从[0,1)随机取的双精度浮点数,计算矩阵跟自身相乘,需要100万次乘法运算。
机器配置:Linux云主机,8核16G内存。
分别尝试开10、100、1000、10000、100000、1000000个线程(协程)执行上述的基本任务。
试验结果:
| 测试运行时间/ms | ||||||
| 并发度 | 10 | 100 | 1000 | 10000 | 100000 | 1000000 |
| go | 0 | 5 | 56 | 507 | 5062 | 50457 |
| java | 36 | 109 | 611 | 3063 | 27684 | 285971 |
速度差异很明显,go以绝对优势领先。而且随着并发度的增加,go的耗时呈线性增长;java则愈显吃力,Hold不住这么高的并发量。go可以轻松地把8个核用满,而java最多只用到5.2个核。
最后附上测试代码,如有问题,还请指正。
go:
package main
import (
"fmt"
"math/rand"
"os"
"strconv"
"sync"
"time"
)
func MatrixMultiply(A, B [100][100]float64) {
rect := [100][100]float64{}
for i := 0; i < 100; i++ {
for j := 0; j < 100; j++ {
prod := 0.0
for k := 0; k < 100; k++ {
prod += A[i][k] * B[k][j]
}
rect[i][j] = prod
}
}
// fmt.Println("goroutine finish")
}
func main() {
A := [100][100]float64{}
for i := 0; i < 100; i++ {
for j := 0; j < 100; j++ {
A[i][j] = rand.Float64() //[0,1)上的随机数
}
}
p, _ := strconv.Atoi(os.Args[1]) //p个并发协程
fmt.Printf("concurrency %d
", p)
begin := time.Now()
wg := sync.WaitGroup{}
wg.Add(p)
for i := 0; i < p; i++ {
go func() {
defer wg.Done()
MatrixMultiply(A, A)
}()
}
wg.Wait()
fmt.Printf("use time %d ms
", time.Since(begin).Milliseconds())
}
java:
import java.util.Random;
public class MatMul extends Thread{
private double[][] A;
private double[][] B;
MatMul(double[][] X, double[][] Y){
A=X;
B=Y;
}
@Override
public void run(){
double[][] rect=new double[100][100];
for(int i=0;i<100;i++){
for(int j=0;j<100;j++){
double prod=0;
for(int k=0;k<100;k++){
prod+=A[i][k]*B[k][j];
}
rect[i][j]=prod;
}
}
// System.out.println("thread finish");
}
public static void main(String[] args) {
Random r = new Random(1);
double[][] A=new double[100][100];
for(int i=0;i<100;i++){
for(int j=0;j<100;j++){
A[i][j]=r.nextDouble();//[0,1)上的随机数
}
}
int p=Integer.parseInt(args[0]);//p个并发线程
System.out.println("concurrency "+p);
MatMul[] threads=new MatMul[p];
long startTime = System.currentTimeMillis();
for(int i=0;i<p;i++){
MatMul thread=new MatMul(A,A);
threads[i]=thread;
thread.start();
}
for(int i=0;i<p;i++){
try {
threads[i].join();
}catch(InterruptedException e) {
System.out.println("Thread interrupted.");
}
}
long endTime = System.currentTimeMillis();
System.out.println("use time "+(endTime-startTime)+" ms");
}
}