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

分享于2021年11月16日 go java 并发
我一直想讨论 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 的接口。GolangGoroutine 开始同步过程Java方法上的同步块。使用 java.util.concurrent 包中的 Lock.ReentrantLockGolang使用通道的概念,即术语“不通过共享内存进行通信和通过通信共享内存”的行话的实现。Sync.Mutex 锁定资源。进程间通讯Java使用 object.wait(),object.Notify() 或 object.NotifyAll() 方法。在多个线程上共享块队列使用 PipeReader 和 PipeWriter 方法Golang使用 channel使用 WaitGroup样例代码SampleTask.javapackage com.dhfr.concurrency;import java.util.concurrent.TimeUnit;public class SampleTask implements Runnable {    private String name;    public SampleTask(String name) {        this.name = name;    }    public String getName() {        return name;    }    public void run() {        Long timeDuration = (long)Math.random() * 11;        System.out.println(\"Pengerjaan Task \"+ name);        try {            TimeUnit.SECONDS.sleep(timeDuration);        } catch (InterruptedException e) {            e.printStackTrace();        }    }}ApplicationMain.javapackage com.dhfr.concurrency;import java.util.concurrent.Executors;import java.util.concurrent.ThreadPoolExecutor;public class ApplicationMain {    public static void main(String[] args) {        ThreadPoolExecutor threadPoolExecutor= (ThreadPoolExecutor) Executors.newFixedThreadPool(6);        for (int i=0;i<10;i++) {            SampleTask sampleTask=new SampleTask(\"Task ke \"+i) ;            System.out.println(\"Sebuah task sudah di tambahkan dengan nama \"+sampleTask.getName());            threadPoolExecutor.execute(sampleTask);        }        System.out.println(\"Maksimun thread yang terjadi adalah \"+threadPoolExecutor.getMaximumPoolSize());        threadPoolExecutor.shutdown();    }}view raw如果我们执行上面的代码,产生如下输出:SSebuah task sudah di tambahkan dengan nama Task ke 0Sebuah task sudah di tambahkan dengan nama Task ke 1Sebuah task sudah di tambahkan dengan nama Task ke 2Sebuah task sudah di tambahkan dengan nama Task ke 3Sebuah task sudah di tambahkan dengan nama Task ke 4Sebuah task sudah di tambahkan dengan nama Task ke 5Sebuah task sudah di tambahkan dengan nama Task ke 6Sebuah task sudah di tambahkan dengan nama Task ke 7Sebuah task sudah di tambahkan dengan nama Task ke 8Sebuah task sudah di tambahkan dengan nama Task ke 9Maksimun thread yang terjadi adalah 6Pengerjaan Task Task ke 0Pengerjaan Task Task ke 1Pengerjaan Task Task ke 3Pengerjaan Task Task ke 2Pengerjaan Task Task ke 4Pengerjaan Task Task ke 5Pengerjaan Task Task ke 9Pengerjaan Task Task ke 8Pengerjaan Task Task ke 7Pengerjaan Task Task ke 6Process finished with exit code 0从上面的代码输出中可以看出,由于提供的线程数为 6,因此该过程是异步执行的。例如,如果我们创建一个 1 的线程池,则结果始终如下所示。Sebuah task sudah di tambahkan dengan nama Task ke 0Sebuah task sudah di tambahkan dengan nama Task ke 1Sebuah task sudah di tambahkan dengan nama Task ke 2Sebuah task sudah di tambahkan dengan nama Task ke 3Sebuah task sudah di tambahkan dengan nama Task ke 4Sebuah task sudah di tambahkan dengan nama Task ke 5Sebuah task sudah di tambahkan dengan nama Task ke 6Sebuah task sudah di tambahkan dengan nama Task ke 7Sebuah task sudah di tambahkan dengan nama Task ke 8Sebuah task sudah di tambahkan dengan nama Task ke 9Maksimun thread yang terjadi adalah 1Pengerjaan Task Task ke 0Pengerjaan Task Task ke 1Pengerjaan Task Task ke 2Pengerjaan Task Task ke 3Pengerjaan Task Task ke 4Pengerjaan Task Task ke 5Pengerjaan Task Task ke 6Pengerjaan Task Task ke 7Pengerjaan Task Task ke 8Pengerjaan Task Task ke 9Process finished with exit code 0因为只有 1 个池可用,所以该过程是同步完成的。main.gopackage mainimport (   \"fmt\"   \"runtime\")func main() {   numberOfCPU := runtime.NumCPU()   runtime.GOMAXPROCS(numberOfCPU)   /* Jumlah bilangan prima yang akan di generate    */   const maxNumber = 30   ch := make(chan int)   defer close(ch)   go Generate(ch)   for i := 0; i < maxNumber; i++ {      fmt.Println(\"Urutan loop  ke : \",i+1)      prime := <-ch      fmt.Println(\"Angka bilangan prima hasil generate adalah \", prime)      ch1 := make(chan int)      go Filter(ch, ch1, prime)      ch = ch1   }}func Generate(ch chan<- int) {   for i := 2; ; i++ {      ch <- i   }}func Filter(in <-chan int, out chan<- int, prime int) {   for {      i := <-in      if i%prime != 0 {         out <- i      }   }}如果我们执行上面的 golang 代码,将获得以下输出。Urutan loop  ke :  1Angka bilangan prima hasil generate adalah  2Urutan loop  ke :  2Angka bilangan prima hasil generate adalah  3Urutan loop  ke :  3Angka bilangan prima hasil generate adalah  5Urutan loop  ke :  4Angka bilangan prima hasil generate adalah  7Urutan loop  ke :  5Angka bilangan prima hasil generate adalah  11Urutan loop  ke :  6Angka bilangan prima hasil generate adalah  13Urutan loop  ke :  7Angka bilangan prima hasil generate adalah  17Urutan loop  ke :  8Angka bilangan prima hasil generate adalah  19Urutan loop  ke :  9Angka bilangan prima hasil generate adalah  23Urutan loop  ke :  10Angka bilangan prima hasil generate adalah  29Urutan loop  ke :  11Angka bilangan prima hasil generate adalah  31Urutan loop  ke :  12Angka bilangan prima hasil generate adalah  37Urutan loop  ke :  13Angka bilangan prima hasil generate adalah  41Urutan loop  ke :  14Angka bilangan prima hasil generate adalah  43Urutan loop  ke :  15Angka bilangan prima hasil generate adalah  47Urutan loop  ke :  16Angka bilangan prima hasil generate adalah  53Urutan loop  ke :  17Angka bilangan prima hasil generate adalah  59Urutan loop  ke :  18Angka bilangan prima hasil generate adalah  61Urutan loop  ke :  19Angka bilangan prima hasil generate adalah  67Urutan loop  ke :  20Angka bilangan prima hasil generate adalah  71Urutan loop  ke :  21Angka bilangan prima hasil generate adalah  73Urutan loop  ke :  22Angka bilangan prima hasil generate adalah  79Urutan loop  ke :  23Angka bilangan prima hasil generate adalah  83Urutan loop  ke :  24Angka bilangan prima hasil generate adalah  89Urutan loop  ke :  25Angka bilangan prima hasil generate adalah  97Urutan loop  ke :  26Angka bilangan prima hasil generate adalah  101Urutan loop  ke :  27Angka bilangan prima hasil generate adalah  103Urutan loop  ke :  28Angka bilangan prima hasil generate adalah  107Urutan loop  ke :  29Angka bilangan prima hasil generate adalah  109Urutan loop  ke :  30Angka bilangan prima hasil generate adalah  113Process finished with exit code 0从上面的代码中,可以在 go 例程中运行方法的命令,即可将 go 命令添加到要处理的方法的前面。这是 Golang 和 Java 如何在并发上实现的比较。我们不讨论哪一个具有更好的性能。Go和Java编程语言各有优缺点。原文链接:https://medium.com/the-legend/golang-vs-java-concurrency-351ca5a845cb推荐阅读Go 中优化字符串的比较操作福利我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。