Go 并发优秀在哪里,需要通过实际的测试,benchmark等说明

参考解析

题目来源:Shopee

答案:

Go中天然的支持并发,Go允许使用go语句开启一个新的运行期线程,即 goroutine,以一个不同的、新创建的goroutine来执行一个函数。同一个程序中的所有goroutine共享同一个地址空间。
Goroutine非常轻量,除了为之分配的栈空间,其所占用的内存空间微乎其微。并且其栈空间在开始时非常小,之后随着堆存储空间的按需分配或释放而变化。内部实现上,goroutine会在多个操作系统线程上多路复用。如果一个goroutine阻塞了一个操作系统线程,例如:等待输入,这个线程上的其他goroutine就会迁移到其他线程,这样能继续运行。开发者并不需要关心/担心这些细节。
Go语言的并发机制运用起来非常简便,在启动并发的方式上直接添加了语言级的关键字就可以实现,和其他编程语言相比更加轻量。

  1. Go语言并发测试
    参考:
    https://blog.csdn.net/SeanBollock1/article/details/79536069?spm=1001.2101.3001.6661.1&utm\_medium=distribute.pc\_relevant\_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1-79536069-blog-102608785.topblog&depth\_1-utm\_source=distribute.pc\_relevant\_t0.none-task-blog-2%7Edefault%7ECTRLIST%7ETopBlog-1-79536069-blog-102608785.topblog&utm\_relevant\_index=1

  2. 与java的比较:
    参考:
    https://blog.csdn.net/weixin\_35657099/article/details/114099451?utm\_medium=distribute.pc\_relevant.none-task-blog-2defaultbaidujs\_baidulandingword~default-8-114099451-blog-79536069.pc\_relevant\_default&spm=1001.2101.3001.4242.5&utm\_relevant\_index=11

测试环境:cpu:2.8 GHz 四核Intel Core i7

内存:16 GB 1600 MHz DDR3

jdk版本:1.8

go版本:1.14

测试方法:分别使用golang和java并发执行相同数量的空任务

golang使用goroutine实现,代码如下:

  1. func main() {
  2. count,line := 100*10000,"-------------------------------------"
  3. runTask(count)
  4. fmt.Println(line)
  5. count = 1000*10000
  6. runTask(count)
  7. fmt.Println(line)
  8. count = 10000*10000
  9. runTask(count)
  10. }
  11. func runTask(taskCount int) {
  12. runtime.GOMAXPROCS(runtime.NumCPU())
  13. fmt.Println("golang并发测试")
  14. fmt.Printf("processors=%d
  15. ", runtime.NumCPU())
  16. fmt.Printf("tasks=%d
  17. ", taskCount)
  18. t1 := time.Now()
  19. for i:=0; i
  20. go func() {}()
  21. }
  22. //for runtime.NumGoroutine() > 4 {
  23. //fmt.Println("current goroutines:", runtime.NumGoroutine())
  24. //time.Sleep(time.Second)
  25. //}
  26. t2 := time.Now()
  27. fmt.Printf("cost time: %.3fs
  28. ", t2.Sub(t1).Seconds())
  29. }

java使用线程池实现,代码如下:

  1. public static void main(String[] args) throws Exception {
  2. int count = 100*10000;
  3. String line = "-------------------------------------";
  4. runTask(count);
  5. System.out.println(line);
  6. count = 1000*10000;
  7. runTask(count);
  8. System.out.println(line);
  9. count = 10000*10000;
  10. runTask(count);
  11. }
  12. public static void runTask(int taskCount){
  13. int d = Runtime.getRuntime().availableProcessors();
  14. System.out.println("java并发测试");
  15. System.out.printf("processors=%d
  16. ",d);
  17. System.out.printf("tasks=%d
  18. ",taskCount);
  19. ExecutorService service = Executors.newFixedThreadPool(d);
  20. long start = System.currentTimeMillis();
  21. for (int i=0;i
  22. service.submit(() -> {});
  23. }
  24. service.shutdown();
  25. long end = System.currentTimeMillis();
  26. System.out.printf("cost time: %.3fs
  27. ", (end-start)/1000f);
  28. }

golang测试结果:

  1. golang并发测试
  2. processors=8
  3. tasks=1000000
  4. cost time: 0.291s
  5. golang并发测试
  6. processors=8
  7. tasks=10000000
  8. cost time: 3.090s
  9. golang并发测试
  10. processors=8
  11. tasks=100000000
  12. cost time: 34.591s

java测试结果:

  1. java并发测试
  2. processors=8
  3. tasks=1000000
  4. cost time: 0.313s
  5. java并发测试
  6. processors=8
  7. tasks=10000000
  8. cost time: 6.239s
  9. java并发测试
  10. processors=8
  11. tasks=100000000
  12. Exception in thread "pool-3-thread-1"

结论:golang在处理并发上要优于java!

当并发在百万量级时,golang比java快7%,优势不明显;

当并发在千万量级时,golang比java快2倍以上,优势明显;

当并发在1亿时,golang能够在35秒内处理完成,而java则会在数分钟后抛异常导致程序崩溃。