为什么Java坚持多线程不选择协程

之所以Java坚持多线程不选择协程,是因为虽然协程是非常值得学习的概念,它是多任务编程的未来,但是Java全力推进这个事情的动力并不大。当我们希望引入协程,不外乎是因为节省资源以及轻量,但Java全力推进这个事情的动力并不大。

为什么Java坚持多线程不选择协程-Worktile社区

协程是非常值得学习的概念,它是多任务编程的未来。但是Java全力推进这个事情的动力并不大。

为什么Java坚持多线程不选择协程?先返回到问题的本源。当我们希望引入协程,我们想解决什么问题。我想不外乎下面几点:节省资源,轻量,具体就是:节省内存,每个线程需要分配一段栈内存,以及内核里的一些资源

节省分配线程的开销(创建和销毁线程要各做一次syscall)

节省大量线程切换带来的开销

与NIO配合实现非阻塞的编程,提高系统的吞吐

使用起来更加舒服顺畅(async+await,跑起来是异步的,但写起来感觉上是同步的)

我们分开来讲下。

先说内存。拿Java Web编程举例子,一个tomcat上的woker线程池的最大线程数一般会配置为50~500之间(目前springboot的默认值给的200)。也就是说同一时刻可以接受的请求非常多也就是这么多。如果超过了最大值,请求直接打失败拒绝处理。假如每个线程给128KB,500个线程放一起的内存占用量大概是60+MB。如果真的有瓶颈,也许CPU,IO,带宽,DB的CPU等会有瓶颈,但这点内存量的增幅对于动辄数个GB的Java运行时进程来说似乎并不是什么大问题。上面的讨论简化了RSS和VM的区别。实际上一个线程启动后只会在虚拟地址上占位置那么多的内存。除非实际用上,是不会真的消耗物理内存的。

换一个场景,比如IM服务器,需要同时处理大量空闲的链接(可能要几十万,上百万)。这时候用connection per thread就很不划算了。但是可以直接改用netty去处理这类问题。你可以理解为NIO + woker thread大致就是一套“协程”,只不过没有实现在语法层面,写起来不优雅而已。问题是,你的场景真的处理了并发几十万,上百万的连接吗?

再说创建/销毁线程的开销。这个问题在Java里通过线程池得到了很好的解决。你会发现即便你用vert.x或者kotlin的协程,归根到底也是要靠线程池工作的。goroutine相当于设置一个全局的“线程池”,GOMAXPROCS就是线程池的最大数量;而Java可以自由设置多个不同的线程池(比如处理请求一套,异步任务另外一套等)。kotlin利用这个机制来构建多个不同的协程scope。这看起来似乎会更灵活一点。

然后是线程的切换开销。线程的切换实际上只会发生在那些“活跃”的线程上。对于类似于Web的场景,大量的线程实际上因为IO(发请求/读DB)而挂起,根本不会参与OS的线程切换。现实当中一个最大200线程的服务器可能同一时刻的“活跃线程”总数只有数十而已。其开销没有想象的那么大。为了避免过大的线程切换开销,真正要防范的是同时有大量“活跃线程”。这个事情我自己上学的时候干过,当时是写了一个网络模拟器。每一个节点,每一个链路都由一个线程实现。模拟跑起来后,同时的活跃线程上千。当时整个机器瞬间卡死,直到kill掉这个程序。

此外说说与NIO的配合。在Java这个生态里Java NIO/Netty/Vert.X/rxJava/Akka可以任意选择。一般来讲,Netty可以解决绝大部分因为IO的等待造成资源浪费的问题。Vert.X/rxJava。可以让程序写的更加“优雅”一点(见仁见智)。Akka就是Java世界里对“原教旨OO“的实现,很有特色。的确,用NIO + completedFuture/handler/lambda不如async+await写起来舒服,但起码是可以干活的。

如果真的要较真Java的NIO用于业务的问题,其核心痛点应该是JDBC。这是个诞生了几十年的,必须使用Blocking IO的DB交互协议。其上承载了Java庞大的生态和业务逻辑。Java要改自己的编程方式,必须得重新设计和实现JDBC,就像https://github.com/vert-x3/vertx-mysql-postgresql-client 那样做。问题是,社区里这种“异步JDBC”还没有支持oracle、sql server等传统DB。对mysql和postgres的支持还需要继续趟坑~

如果认真阅读上面这些需要“协程”解决的问题,就会发现基本上都可以以各种方式解决。觉得线程耗资源,可以控制线程总数,可以减少线程stack的大小,可以用线程池配置max和min idle等等。想要go的channel,可以上disruptor。可以说,Java这个生态里尽管没有“协程”这个名列前茅级别的概念,但是要解决问题的工具并不缺。

Java仅仅是没有解决”协程“在Java中的定义,以及“写得优雅“这个问题。从工程角度,“写得优雅”的优势并没有很多追新的人想象的那么关键。C#也并非因为有了async await就抢了Java的市场分毫。而反过来,如果java社区全力推进这个事情,Java历史上的生态的积累却因为协程的出现而进行大换血。想像一下如果没有thread,也没有ThreadLocal,@Transactional不起作用了,又没有等价的工具,是不是很郁闷?这么看来怎么着都不是个划算的事情。我想Oracle对此并不会有太大兴趣。OpenJDK的loom能不能成,如果真的release多少Java程序员愿意使用,师母已呆。据我所知在9012年的今天,还有大量的Java6程序员。

其他新的语言历史包袱少,比较容易重新思考“什么是现代的multi-task编程的方式“这个大主题。kotlin的协程、go的goroutine、javascript的async await、python的asyncio、swift的GCD都给了各自的答案。如果真的想入坑Java这个体系的“协程”,就从kotlin开始吧,毕竟可以混合编程。

最后说一句,多线程容易出bug主要因为:“抢占“式的线程切换 —— 你无法确定两个线程访问数据的顺序,一切都很随机

“同步“不可组装 —— 同步的代码组装起来也不同步,必须加个更大的同步块

协程能不能避免容易出bug的缺陷,主要看能不能避免上面两个问题。如果协程底层用的还是线程池,两个协程还是通过共享内存通讯,那么多线程该出什么bug,多协程照样出。javascript里不出这种bug是因为其用户线程就一个,不会出现线程切换,也不用同步;go是建议用channel做goroutine的通讯。如果go routine不用channel,而是用共享变量,并且没有用Sync包控制一下,还是会出bug。

延伸阅读:

什么是Java?

Java programming language具有大部分编程语言所共有的一些特征,被特意设计用于互联网的分布式环境。Java具有类似于C++语言的”形式和感觉”,但它要比C++语言更易于使用,而且在编程时彻底采用了一种”以对象为导向”的方式。使用Java编写的应用程序,既可以在一台单独的电脑上运行,也可以被分布在一个网络的服务器端和客户端运行。另外,Java还可以被用来编写容量很小的应用程序模块或者applet,做为网页的一部分使用。applet可使网页使用者和网页之间进行交互式操作。

Java是Sun微系统公司在1995年推出的,推出之后马上给互联网的交互式应用带来了新面貌。最常用的两种互联网浏览器软件中都包括一个Java虚拟机。几乎所有的操作系统中都增添了Java编译程序。

Java是一种编程语言,被特意设计用于互联网的分布式环境。Java具有类似于C++语言的“形式和感觉”,但它要比C++语言更易于使用,而且在编程时彻底采用了一种“以对象为导向”的方式。

使用Java编写的应用程序,既可以在一台单独的电脑上运行,也可以被分布在一个网络的服务器端和客户端运行。另外,Java还可以被用来编写容量很小的应用程序模块或者applet,做为网页的一部分使用。applet可使网页使用者和网页之间进行交互式操作。

文章标题:为什么Java坚持多线程不选择协程,发布者:小编,转载请注明出处:https://worktile.com/kb/p/35976

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
小编小编认证作者
上一篇 2023年1月27日 下午8:37
下一篇 2023年1月27日 下午8:40

相关推荐

  • 编程属于什么系统

    编程属于计算机科学系统,其中,1、编程语言作为一种重要的工具在整个计算机科学系统中占据着中心地位。编程语言不仅是计算机与用户之间交流的桥梁,也是实现算法、处理数据和开发软件的基础。在众多的编程语言中,如Python、Java、C++等,它们各自因其独特的特性和优势,被广泛应用于不同的领域,如人工智能…

    2024年5月2日
    3200
  • 编程qt用什么电脑强大

    关于选择适合编程QT的电脑,几个关键因素包括1、处理器性能、2、内存容量、3、硬盘速度与容量。具体来说,处理器直接影响编译代码的速度,其中处理器性能对QT开发尤为关键。一个强大的CPU可以显著缩短编译时间,提高开发效率。对于QT开发,推荐至少使用四核心的处理器,例如英特尔的i5或i7系列,或是AMD…

    2024年4月27日
    4900
  • 电脑编程学什么班

    参加计算机编程课程时,重要的领域包括1、基础编程语言理解、2、算法和数据结构、3、版本控制系统使用、4、项目管理工具和技术、5、软件开发生命周期。 深入探讨基础编程语言理解,它是编程学习的基石。入门者首先需掌握至少一种编程语言的基础知识,常见的选择包括Python、Java、C++等。这一阶段不仅是…

    2024年4月26日
    5900
  • 什么叫sc编程

    SC编程,即智能合约(Smart Contract)编程,是区块链技术的核心应用之一。1、它允许在没有中介的情况下,在各方之间创建信任和执行自动化交易。2、具体而言,智能合约编程涉及编写符合特定协议的代码,这些代码在满足预设条件时自动执行预定的操作。 智能合约的自动执行能力极大地降低了交易成本和时间…

    2024年5月2日
    2800
  • 编程都在学什么

    编程学习包括主题如下:1、基础语法与概念、2、算法与数据结构、3、项目和实战经验、4、软件开发生命周期、5、版本控制系统和6、编程范式。特别着重于算法与数据结构,因为它们是编程的核心,涉及到如何有效地组织和操作数据,解决问题的方法和技术。掌握良好的算法和数据结构知识,可以帮助编程者编写出更高效、更优…

    2024年5月2日
    3200
  • 学习软件编程什么学校好

    学习软件编程的优秀选择中,重点关注的机构有1、顶尖理工大学、2、专业编程训练营、3、在线编程学习平台。尤其是顶尖理工大学,不仅因为它们提供深入的理论基础和实战训练,而且能够与行业内的专业人士建立联系。学生在这里不仅能学到最前沿的编程知识,也能通过项目实践深化理解,毕业后更容易获得理想工作或进一步的教…

    2024年4月27日
    4700
  • 编程启蒙学什么

    编程启蒙教育应包括以下几个关键组成部分:1、基础逻辑能力培养;2、简单编程语言学习;3、创意思维促进;4、解决问题的方法论。 在编程启蒙的初步阶段,关键是培养孩子的基础逻辑能力。逻辑能力是编程的核心,也是儿童早期认知发展中一项至关重要的技能。通过学习如何通过序列化的步骤解决问题,孩子可以理解因果关系…

    2024年5月2日
    4000
  • 信息系统项目管理师报名费是多少

    信息系统项目管理师报名费用根据不同地区和考试年份会有所变化,通常报名费在几百元至一千元人民币区间内。例如,某个地区的报名费为600元人民币,这涵盖了参加考试所需的全部费用,但不包括备考的辅导书籍和其他材料的开销。在6、7月份时,考生通常需要关注各省市相关部门发布的考试通知,以了解当年的具体报名费用和…

    2024年1月8日
    37700
  • 特殊ug编程方式是什么

    特殊UG编程方式主要包括1、参数化编程、2、宏编程、3、知识库编程。参数化编程是其中的核心,它允许用户通过参数控制模型的行为,从而实现快速定制和修改。 特殊UG编程方式允许使用者通过编程来控制UG(现在称为Siemens NX)软件的行为,以高效、自动化地完成设计和制造任务。这种方式能够显著提升工作…

    2024年5月6日
    1300
  • 编程变量是什么

    变量是一种存储信息的单位,在编程中用以标示数据。其用途有两个主要方面,第一、为内存中特定位置命名以方便存取数据;二、变量在存储与操作数据时提供方便。变量可以看成是邮件箱,我们将数据放入这个“箱子”中,程序中其它部分通过变量名引用和处理这些数据。在编程实践中,选择有意义的变量名对于提高代码的可读性和可…

    2024年5月2日
    3300

发表回复

登录后才能评论
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部