Java 和 Go 在并发实现中的区别

开发 后端
我一直想讨论 Golang 和 Java,许多朋友都希望讨论下。而我碰巧有相当长的 Java 编程语言经验,并且在过去的几年中,我接触并使用了 Golang。

[[434370]]

我一直想讨论 Golang 和 Java,许多朋友都希望讨论下。而我碰巧有相当长的 Java 编程语言经验,并且在过去的几年中,我接触并使用了 Golang。

Java 是一门高级编程语言,在实现其语言时采用了对象方法。Java 是一种非常成熟和稳定的编程语言,在世界上使用最广泛。特别是对于企业级别平均超过 80% 的应用程序,使用的都是 Java。Java 本身是在 1990 年左右由 SUN Microsystems 开发的。

Golang 是由 Google 创建的一种编程语言,在 2009 年左右开源,Golang 最初使用 C 实现的。与 Java 一样拥有垃圾收集,不同之处在于 Golang 代码将被编译为计算机本地代码,因此与基于虚拟机的编程语言相比,它会有更好的性能。

Golang 几乎像 Java 等 OOP 一样,但是它不是完全的 OOP,或者现在还不能被称为完全的 OOP 编程语言。由于其缺乏对 OOP 的支持,有些特性会比较麻烦。但面向对象有它自己的问题。Go 强调使用组合来复用,而不是继承。

并发是一种用于解决多个请求或多个进程同时完成的问题的编程技术,并发进程的主要特征是不能在某个资源上同时执行一个进程和另一个进程。通常一个进程与另一个进程交替进行。因为它非常快,所以有时看起来好像是一起完成的。

如果我们尝试进行分析,那么这个并发过程就像处理许多请求的饭店工作人员。他将堆积所有即将到来的请求,并一一完成。这样,如果所有进程都由他们自己执行,则该进程将花费很长时间,因为会发生队列并且这些工作人员都已耗尽。为了处理这些许多请求,解决方案是增加额外的工作人员,以便可以同时执行工作流程,并更快地为访问者的请求提供服务。

它与并行性的概念不同,并行性有时会与并发性概念混淆。并行处理是解决大问题的一种方法,通常这样做会花费很长时间。通过将解决方案分成更小的部分来完成解决方案。这些小任务是独立的,互不影响,并且同时完成。

在并行编程技术中,必须存在并发,但是并发并不一定意味着存在并行进程。

并发与并行的区别

Java 使用 OS 线程通过 Java 运行时管理的线程来完成并行进程。Golang 通过 Goroutine 使用线程 os 完成并行进程。在 Java 和 Golang 之间的并行概念中,没有太大区别,几乎相同,只是名称不同。

并发概念不同。在 Java 中,这是通过将 Java 运行时线程映射到 os线 程来完成的。同时,golang 使用此 goroutine 映射到 golang 上的调度程序,将其映射到更深层次。

Goroutine 本身不是线程系统或由 os 线程管理的线程。但是,这种想法更多的是将函数协程处理到 os 线程中的多路复用器。这样,当发生进程阻塞时,它将被移至未使用的线程或绿色线程,Go 调度程序的任务是将此绿色线程映射到 OS 线程,并将 goroutine 分配到空闲的绿色线程中。

乍一看,goroutine 概念与 Reactive .io 中以 Reactore 3 或 RxJava 表示的 React Java 的非阻塞概念几乎相同。但是,Java反 应流概念比 goroutines 具有更高级的方法。

Java 并发模型和 Golang

尽管在并发问题中有不同的实现方法,但是模型几乎相同。

异步过程

Java

  • 创建从 Thread 类扩展的类。
  • 实现 Runnable 的接口。

Golang

  • Goroutine 开始

同步过程

Java

  • 方法上的同步块。
  • 使用 java.util.concurrent 包中的 Lock.ReentrantLock

Golang

  • 使用通道的概念,即术语“不通过共享内存进行通信和通过通信共享内存”的行话的实现。
  • Sync.Mutex 锁定资源。

进程间通讯

Java

  • 使用 object.wait(),object.Notify() 或 object.NotifyAll() 方法。
  • 在多个线程上共享块队列
  • 使用 PipeReader 和 PipeWriter 方法

Golang

  • 使用 channel
  • 使用 WaitGroup

样例代码

SampleTask.java

  1. package com.dhfr.concurrency; 
  2.  
  3. import java.util.concurrent.TimeUnit; 
  4.  
  5. public class SampleTask implements Runnable { 
  6.  
  7.     private String name
  8.  
  9.     public SampleTask(String name) { 
  10.         this.name = name
  11.     } 
  12.  
  13.     public String getName() { 
  14.         return name
  15.     } 
  16.  
  17.     public void run() { 
  18.         Long timeDuration = (long)Math.random() * 11; 
  19.         System.out.println("Pengerjaan Task "name); 
  20.         try { 
  21.             TimeUnit.SECONDS.sleep(timeDuration); 
  22.         } catch (InterruptedException e) { 
  23.             e.printStackTrace(); 
  24.         } 
  25.  
  26.     } 

ApplicationMain.java

  1. package com.dhfr.concurrency; 
  2.  
  3. import java.util.concurrent.Executors; 
  4. import java.util.concurrent.ThreadPoolExecutor; 
  5.  
  6. public class ApplicationMain { 
  7.  
  8.     public static void main(String[] args) { 
  9.  
  10.         ThreadPoolExecutor threadPoolExecutor= (ThreadPoolExecutor) Executors.newFixedThreadPool(6); 
  11.         for (int i=0;i<10;i++) { 
  12.             SampleTask sampleTask=new SampleTask("Task ke "+i) ; 
  13.             System.out.println("Sebuah task sudah di tambahkan dengan nama "+sampleTask.getName()); 
  14.             threadPoolExecutor.execute(sampleTask); 
  15.         } 
  16.         System.out.println("Maksimun thread yang terjadi adalah "+threadPoolExecutor.getMaximumPoolSize()); 
  17.         threadPoolExecutor.shutdown(); 
  18.     } 
  19. view raw 

如果我们执行上面的代码,产生如下输出:

  1. SSebuah task sudah di tambahkan dengan nama Task ke 0 
  2. Sebuah task sudah di tambahkan dengan nama Task ke 1 
  3. Sebuah task sudah di tambahkan dengan nama Task ke 2 
  4. Sebuah task sudah di tambahkan dengan nama Task ke 3 
  5. Sebuah task sudah di tambahkan dengan nama Task ke 4 
  6. Sebuah task sudah di tambahkan dengan nama Task ke 5 
  7. Sebuah task sudah di tambahkan dengan nama Task ke 6 
  8. Sebuah task sudah di tambahkan dengan nama Task ke 7 
  9. Sebuah task sudah di tambahkan dengan nama Task ke 8 
  10. Sebuah task sudah di tambahkan dengan nama Task ke 9 
  11. Maksimun thread yang terjadi adalah 6 
  12. Pengerjaan Task Task ke 0 
  13. Pengerjaan Task Task ke 1 
  14. Pengerjaan Task Task ke 3 
  15. Pengerjaan Task Task ke 2 
  16. Pengerjaan Task Task ke 4 
  17. Pengerjaan Task Task ke 5 
  18. Pengerjaan Task Task ke 9 
  19. Pengerjaan Task Task ke 8 
  20. Pengerjaan Task Task ke 7 
  21. Pengerjaan Task Task ke 6 
  22. Process finished with exit code 0 

从上面的代码输出中可以看出,由于提供的线程数为 6,因此该过程是异步执行的。例如,如果我们创建一个 1 的线程池,则结果始终如下所示。

  1. Sebuah task sudah di tambahkan dengan nama Task ke 0 
  2. Sebuah task sudah di tambahkan dengan nama Task ke 1 
  3. Sebuah task sudah di tambahkan dengan nama Task ke 2 
  4. Sebuah task sudah di tambahkan dengan nama Task ke 3 
  5. Sebuah task sudah di tambahkan dengan nama Task ke 4 
  6. Sebuah task sudah di tambahkan dengan nama Task ke 5 
  7. Sebuah task sudah di tambahkan dengan nama Task ke 6 
  8. Sebuah task sudah di tambahkan dengan nama Task ke 7 
  9. Sebuah task sudah di tambahkan dengan nama Task ke 8 
  10. Sebuah task sudah di tambahkan dengan nama Task ke 9 
  11. Maksimun thread yang terjadi adalah 1 
  12. Pengerjaan Task Task ke 0 
  13. Pengerjaan Task Task ke 1 
  14. Pengerjaan Task Task ke 2 
  15. Pengerjaan Task Task ke 3 
  16. Pengerjaan Task Task ke 4 
  17. Pengerjaan Task Task ke 5 
  18. Pengerjaan Task Task ke 6 
  19. Pengerjaan Task Task ke 7 
  20. Pengerjaan Task Task ke 8 
  21. Pengerjaan Task Task ke 9 
  22. Process finished with exit code 0 

因为只有 1 个池可用,所以该过程是同步完成的。

main.go

  1. package main 
  2.  
  3. import ( 
  4.    "fmt" 
  5.    "runtime" 
  6.  
  7. func main() { 
  8.    numberOfCPU := runtime.NumCPU() 
  9.    runtime.GOMAXPROCS(numberOfCPU) 
  10.  
  11.    /* Jumlah bilangan prima yang akan di generate 
  12.     */ 
  13.    const maxNumber = 30 
  14.  
  15.    ch := make(chan int
  16.    defer close(ch) 
  17.    go Generate(ch) 
  18.  
  19.    for i := 0; i < maxNumber; i++ { 
  20.       fmt.Println("Urutan loop  ke : ",i+1) 
  21.       prime := <-ch 
  22.       fmt.Println("Angka bilangan prima hasil generate adalah ", prime) 
  23.       ch1 := make(chan int
  24.       go Filter(ch, ch1, prime) 
  25.       ch = ch1 
  26.    } 
  27.  
  28. func Generate(ch chan<- int) { 
  29.    for i := 2; ; i++ { 
  30.       ch <- i 
  31.    } 
  32.  
  33. func Filter(in <-chan intout chan<- int, prime int) { 
  34.    for { 
  35.       i := <-in 
  36.       if i%prime != 0 { 
  37.          out <- i 
  38.       } 
  39.    } 

如果我们执行上面的 golang 代码,将获得以下输出。

  1. Urutan loop  ke :  1 
  2. Angka bilangan prima hasil generate adalah  2 
  3. Urutan loop  ke :  2 
  4. Angka bilangan prima hasil generate adalah  3 
  5. Urutan loop  ke :  3 
  6. Angka bilangan prima hasil generate adalah  5 
  7. Urutan loop  ke :  4 
  8. Angka bilangan prima hasil generate adalah  7 
  9. Urutan loop  ke :  5 
  10. Angka bilangan prima hasil generate adalah  11 
  11. Urutan loop  ke :  6 
  12. Angka bilangan prima hasil generate adalah  13 
  13. Urutan loop  ke :  7 
  14. Angka bilangan prima hasil generate adalah  17 
  15. Urutan loop  ke :  8 
  16. Angka bilangan prima hasil generate adalah  19 
  17. Urutan loop  ke :  9 
  18. Angka bilangan prima hasil generate adalah  23 
  19. Urutan loop  ke :  10 
  20. Angka bilangan prima hasil generate adalah  29 
  21. Urutan loop  ke :  11 
  22. Angka bilangan prima hasil generate adalah  31 
  23. Urutan loop  ke :  12 
  24. Angka bilangan prima hasil generate adalah  37 
  25. Urutan loop  ke :  13 
  26. Angka bilangan prima hasil generate adalah  41 
  27. Urutan loop  ke :  14 
  28. Angka bilangan prima hasil generate adalah  43 
  29. Urutan loop  ke :  15 
  30. Angka bilangan prima hasil generate adalah  47 
  31. Urutan loop  ke :  16 
  32. Angka bilangan prima hasil generate adalah  53 
  33. Urutan loop  ke :  17 
  34. Angka bilangan prima hasil generate adalah  59 
  35. Urutan loop  ke :  18 
  36. Angka bilangan prima hasil generate adalah  61 
  37. Urutan loop  ke :  19 
  38. Angka bilangan prima hasil generate adalah  67 
  39. Urutan loop  ke :  20 
  40. Angka bilangan prima hasil generate adalah  71 
  41. Urutan loop  ke :  21 
  42. Angka bilangan prima hasil generate adalah  73 
  43. Urutan loop  ke :  22 
  44. Angka bilangan prima hasil generate adalah  79 
  45. Urutan loop  ke :  23 
  46. Angka bilangan prima hasil generate adalah  83 
  47. Urutan loop  ke :  24 
  48. Angka bilangan prima hasil generate adalah  89 
  49. Urutan loop  ke :  25 
  50. Angka bilangan prima hasil generate adalah  97 
  51. Urutan loop  ke :  26 
  52. Angka bilangan prima hasil generate adalah  101 
  53. Urutan loop  ke :  27 
  54. Angka bilangan prima hasil generate adalah  103 
  55. Urutan loop  ke :  28 
  56. Angka bilangan prima hasil generate adalah  107 
  57. Urutan loop  ke :  29 
  58. Angka bilangan prima hasil generate adalah  109 
  59. Urutan loop  ke :  30 
  60. Angka bilangan prima hasil generate adalah  113 
  61. Process finished with exit code 0 

从上面的代码中,可以在 go 例程中运行方法的命令,即可将 go 命令添加到要处理的方法的前面。

这是 Golang 和 Java 如何在并发上实现的比较。我们不讨论哪一个具有更好的性能。Go和Java编程语言各有优缺点。

原文链接:https://medium.com/the-legend/golang-vs-java-concurrency-351ca5a845cb

本文转载自微信公众号「幽鬼」,可以通过以下二维码关注。转载本文请联系幽鬼公众号。

责任编辑:武晓燕 来源: 幽鬼
相关推荐

2022-05-22 13:55:30

Go 语言

2021-10-18 09:08:27

Go分段栈连续栈

2023-11-20 22:44:09

Golang并发

2021-08-17 11:14:49

VoidJSTS

2014-04-09 09:32:24

Go并发

2023-10-12 08:25:18

Javaequals内存

2020-01-14 11:17:33

Go并发Linux

2021-07-02 06:54:45

GoJavachannel

2011-05-20 13:45:30

Java

2018-09-12 15:38:42

Javaatomic编程

2023-03-29 08:03:53

2012-03-01 14:04:03

Java

2023-12-22 14:07:00

Go轻量级Goroutines

2022-03-04 10:07:45

Go语言字节池

2023-11-12 17:19:07

并行并发场景

2022-02-07 23:07:19

Golang语言Modules

2018-09-26 14:37:17

JavaScript前端编程语言

2009-08-04 14:48:26

并发和并行的区别

2021-07-28 08:32:58

Go并发Select

2009-06-19 16:46:18

IntegerJava
点赞
收藏

51CTO技术栈公众号