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

共 2693字,需浏览 6分钟

 ·

2021-11-15 08:02

我一直想讨论 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

package 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.java

package 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 0
Sebuah task sudah di tambahkan dengan nama Task ke 1
Sebuah task sudah di tambahkan dengan nama Task ke 2
Sebuah task sudah di tambahkan dengan nama Task ke 3
Sebuah task sudah di tambahkan dengan nama Task ke 4
Sebuah task sudah di tambahkan dengan nama Task ke 5
Sebuah task sudah di tambahkan dengan nama Task ke 6
Sebuah task sudah di tambahkan dengan nama Task ke 7
Sebuah task sudah di tambahkan dengan nama Task ke 8
Sebuah task sudah di tambahkan dengan nama Task ke 9
Maksimun thread yang terjadi adalah 6
Pengerjaan Task Task ke 0
Pengerjaan Task Task ke 1
Pengerjaan Task Task ke 3
Pengerjaan Task Task ke 2
Pengerjaan Task Task ke 4
Pengerjaan Task Task ke 5
Pengerjaan Task Task ke 9
Pengerjaan Task Task ke 8
Pengerjaan Task Task ke 7
Pengerjaan Task Task ke 6
Process finished with exit code 0

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

Sebuah task sudah di tambahkan dengan nama Task ke 0
Sebuah task sudah di tambahkan dengan nama Task ke 1
Sebuah task sudah di tambahkan dengan nama Task ke 2
Sebuah task sudah di tambahkan dengan nama Task ke 3
Sebuah task sudah di tambahkan dengan nama Task ke 4
Sebuah task sudah di tambahkan dengan nama Task ke 5
Sebuah task sudah di tambahkan dengan nama Task ke 6
Sebuah task sudah di tambahkan dengan nama Task ke 7
Sebuah task sudah di tambahkan dengan nama Task ke 8
Sebuah task sudah di tambahkan dengan nama Task ke 9
Maksimun thread yang terjadi adalah 1
Pengerjaan Task Task ke 0
Pengerjaan Task Task ke 1
Pengerjaan Task Task ke 2
Pengerjaan Task Task ke 3
Pengerjaan Task Task ke 4
Pengerjaan Task Task ke 5
Pengerjaan Task Task ke 6
Pengerjaan Task Task ke 7
Pengerjaan Task Task ke 8
Pengerjaan Task Task ke 9
Process finished with exit code 0

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

main.go

package main

import (
   "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 :  1
Angka bilangan prima hasil generate adalah  2
Urutan loop  ke :  2
Angka bilangan prima hasil generate adalah  3
Urutan loop  ke :  3
Angka bilangan prima hasil generate adalah  5
Urutan loop  ke :  4
Angka bilangan prima hasil generate adalah  7
Urutan loop  ke :  5
Angka bilangan prima hasil generate adalah  11
Urutan loop  ke :  6
Angka bilangan prima hasil generate adalah  13
Urutan loop  ke :  7
Angka bilangan prima hasil generate adalah  17
Urutan loop  ke :  8
Angka bilangan prima hasil generate adalah  19
Urutan loop  ke :  9
Angka bilangan prima hasil generate adalah  23
Urutan loop  ke :  10
Angka bilangan prima hasil generate adalah  29
Urutan loop  ke :  11
Angka bilangan prima hasil generate adalah  31
Urutan loop  ke :  12
Angka bilangan prima hasil generate adalah  37
Urutan loop  ke :  13
Angka bilangan prima hasil generate adalah  41
Urutan loop  ke :  14
Angka bilangan prima hasil generate adalah  43
Urutan loop  ke :  15
Angka bilangan prima hasil generate adalah  47
Urutan loop  ke :  16
Angka bilangan prima hasil generate adalah  53
Urutan loop  ke :  17
Angka bilangan prima hasil generate adalah  59
Urutan loop  ke :  18
Angka bilangan prima hasil generate adalah  61
Urutan loop  ke :  19
Angka bilangan prima hasil generate adalah  67
Urutan loop  ke :  20
Angka bilangan prima hasil generate adalah  71
Urutan loop  ke :  21
Angka bilangan prima hasil generate adalah  73
Urutan loop  ke :  22
Angka bilangan prima hasil generate adalah  79
Urutan loop  ke :  23
Angka bilangan prima hasil generate adalah  83
Urutan loop  ke :  24
Angka bilangan prima hasil generate adalah  89
Urutan loop  ke :  25
Angka bilangan prima hasil generate adalah  97
Urutan loop  ke :  26
Angka bilangan prima hasil generate adalah  101
Urutan loop  ke :  27
Angka bilangan prima hasil generate adalah  103
Urutan loop  ke :  28
Angka bilangan prima hasil generate adalah  107
Urutan loop  ke :  29
Angka bilangan prima hasil generate adalah  109
Urutan loop  ke :  30
Angka bilangan prima hasil generate adalah  113
Process finished with exit code 0

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

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

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



推荐阅读


福利

我为大家整理了一份从入门到进阶的Go学习资料礼包,包含学习建议:入门看什么,进阶看什么。关注公众号 「polarisxu」,回复 ebook 获取;还可以回复「进群」,和数万 Gopher 交流学习。

浏览 47
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报