Java 和 Go 在并发实现中的区别
我一直想讨论 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
推荐阅读