java - Erlang 进程与 Java 线程

标签 java erlang elixir

我正在阅读 "Elixir in Action" book by Saša Jurić, and in the first chapter它说:

Erlang processes are completely isolated from each other. They share no memory, and a crash of one process doesn’t cause a crash of other processes.



Java 线程不也是这样吗?我的意思是当 Java 线程崩溃时,它也不会崩溃其他线程 - 特别是,如果我们正在查看请求处理线程(让我们从本讨论​​中排除 main 线程)

最佳答案

在我之后重复: “这些是不同的范式”
大声说 20 次左右——这是我们目前的口头禅。
如果我们真的必须比较苹果和橙子,那么至少让我们考虑一下“作为水果”的共同方面在哪里相交。
Java“对象”是Java程序员的基本计算单位。也就是说,一个 对象 (基本上是带有封装的 ARM 和腿的结构 somewhat more strictly enforced than in C++ )是您建模世界的主要工具。你认为“这个对象知道/拥有 Data {X,Y,Z} 并对其执行 Functions {A(),B(),C()},携带 Data 无处不在,并且可以通过调用定义为公共(public)接口(interface)一部分的函数/方法与其他对象通信。它是一个名词,而这个名词确实有作用。”。也就是说,您围绕这些计算单位来确定您的思维过程。默认情况下,对象之间发生的事情按顺序发生,崩溃会中断该顺序。它们被称为“对象”,因此(如果我们忽略 Alan Kay 的原始含义)我们得到了“面向对象”。
Erlang“进程”是 Erlang 程序员的基本计算单元。一个 流程 (基本上是在自己的时间和空间中运行的自包含顺序程序)是 Erlanger 对世界进行建模的主要工具(1)。类似于 Java 对象定义封装级别的方式,Erlang 进程也定义了封装级别,但在 Erlang 的情况下,计算单元彼此完全切断。您不能在另一个进程上调用方法或函数,也不能访问其中的任何数据,一个进程甚至不能在与任何其他进程相同的时间上下文中运行,并且无法保证消息接收的顺序相对到可能正在发送消息的其他进程。它们也可能完全位于不同的行星上(而且,想想看,这实际上是合理的)。它们可以彼此独立地崩溃,而其他进程只有在它们有意选择受到影响时才会受到影响(甚至这也涉及消息传递:本质上是注册以接收来自死进程的遗书,而遗书本身并不能保证以任何形式到达相对于整个系统的顺序,您可能会也可能不会选择对此使用react)。
Java 直接在复合算法中处理复杂性:对象如何协同工作来解决问题。它旨在在单个执行上下文中执行此操作,Java 中的默认情况是顺序执行。 Java 中的多线程表示多个运行上下文,并且是一个非常复杂的主题,因为不同时序上下文中的 Activity 会相互影响(以及整个系统:因此,防御性编程、异常方案等)。在 Java 中说“多线程”的含义与在 Erlang 中不同,事实上,在 Erlang 中甚至从未说过这一点,因为它始终是基本情况。请注意,Java 线程意味着与时间相关的隔离,而不是内存或可见引用——Java 中的可见性是通过选择什么是私有(private)的和什么是公共(public)的来手动控制的;系统中普遍可访问的元素必须被设计为“线程安全”和可重入的,通过排队机制进行排序,或者使用锁定机制。简而言之:调度是线程/并发 Java 程序中手动管理的问题。
Erlang 在执行时间(调度)、内存访问和引用可见性方面将每个进程的运行上下文分开,这样做通过完全隔离来简化算法的每个组件。这不仅仅是默认情况,这是该计算模型下唯一可用的情况。这是以永远不知道任何给定操作的确切顺序为代价的,一旦您的处理序列的一部分跨越了消息屏障——因为消息本质上都是网络协议(protocol),并且没有方法调用可以保证在给定的时间内执行语境。这类似于为每个对象创建一个 JVM 实例,并且只允许它们通过套接字进行通信——这在 Java 中是非常麻烦的,但这就是 Erlang 的工作方式(顺便说一句,这也是概念的基础如果人们抛弃了流行语往往包含的面向 Web 的包袱,那么编写“Java 微服务”的过程就变得如此——默认情况下,Erlang 程序是一大群微服务)。一切都与权衡有关。
这些是不同的范式。我们能找到的最接近的共同点是,从程序员的角度来看,Erlang 进程类似于 Java 对象。如果我们必须找到一些东西来比较 Java 线程......好吧,我们根本不会在 Erlang 中找到类似的东西,因为在 Erlang 中没有这样的可比概念。打败一匹死马:这些是不同的范式。如果你用 Erlang 编写一些重要的程序,这将变得显而易见。
请注意,我说的是“这些是不同的范式”,但我什至没有触及 OOP 与 FP 的话题。 “在 Java 中思考”和“在 Erlang 中思考”之间的区别比 OOP 与 FP 更根本。 (事实上​​,我们可以为 Erlang VM 编写一种像 Java 一样工作的 OOP 语言——例如: An implementation of OOP objects in Erlang 。)
虽然 Erlang 的“面向并发”或“面向过程”的基础确实更接近 Alan Kay 在创造术语“面向对象”(2) 时的想法,但这并不是真正的重点。 Kay 的意思是,可以通过将您的计算机切割成离散的块来降低系统的认知复杂性,并且隔离是必要的。 Java 以某种方式实现了这一点,它本质上仍然是过程性的,但围绕称为“类定义”的高阶调度闭包的特殊语法来构建代码。 Erlang 通过拆分每个对象的运行上下文来实现这一点。这意味着 Erlang 的东西不能互相调用方法,但 Java 的东西可以。这意味着 Erlang 的东西可以单独崩溃,而 Java 的东西不能。大量的含义源于这种基本差异——因此是“不同的范式”。权衡。

脚注:

  • 顺便说一下,Erlang 实现了“the actor model”的一个版本,但我们不使用这个术语,因为 Erlang 早于该模型的普及。 Joe 在设计 Erlang 时并没有意识到这一点,并写道 his thesis .
  • Alan Kay 对 what he meant when he coined the term 说了很多“面向对象”,最有趣的是his take关于消息传递(从一个具有自己的时间和内存的独立进程到另一个进程的单向通知)VS 调用(具有共享内存的顺序执行上下文中的函数或方法调用)——以及所呈现的编程接口(interface)之间的界限如何有点模糊由编程语言和底层实现。
  • 关于java - Erlang 进程与 Java 线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32294367/

    相关文章:

    testing - 使用 ExUnit 进行测试时如何伪造 IO 输入?

    具有泛型、比较器和排序错误的 Java 类层次结构

    java - 如何在 Spring Boot 上以相同的方法回滚 2 个事务

    erlang - 查询 Erlang 进程的状态?

    erlang - 我可以使用模块池来决定负载平衡吗?

    erlang - Elixir - 递归列表值的总和

    java - Maven Exec 插件不在 Windows 上使用系统路径?

    java - 如何在Java中按笔划对中文字符串进行排序?

    javascript - Markdown 和转义 Javascript 换行符

    elixir - 如何在 Repo.one 中使用 Repo.get 和 select like