为什么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.流程规范/梳理;2.流程优化;3.流程重组。其中,流程规范/梳理一般适合企业正常运行阶段,流程优化则适合企业任何时期,而流程重组则适合企业变革时期,例如战略改变、商业模式变化等。 1.流程规范/梳理 在一个企业尤其是中小企业建立的初期,由于企业生存的压力,管理者普遍关注市场…

    2022年11月13日
    13400
  • 容器和虚拟机的区别是什么

    容器和虚拟机的区别有以下几个方面:1、速度;2、资源;3、安全性和隔离性;4、可移植性和应用程序共享;5、操作系统要求;6、应用程序的生命周期。说到速度,容器是明显的赢家。它们被设计用来大大减少软件应用程序的加载和运行时间。 一、速度 说到速度,容器是明显的赢家。它们被设计用来大大减少软件应用程序的…

    2023年2月13日
    3900
  • Linux文件权限

    Linux文件权限有:1、对文件进行读操作的权限(用r表示);2、对文件进行写操作的权限(用w表示);3、对文件进行执行操作的权限(用x表示)。对文件进行读操作的权限(用r表示)是指具有读取文件内容的权限。 一、Linux文件权限 1、对文件进行读操作的权限(用r表示) 对于单个文件来说是指具有读取…

    2023年3月23日
    3300
  • 什么软件可以规划行程路线

    可以规划行程路线的软件有:1. Google 地图;2. 高德地图;3. 车来了;4. TripIt;5. Airbnb。Google 地图是一款免费的 Web 应用程序,它可以帮助用户查找地点、获取导航以及规划路线。对于旅行者来说,Google 地图是一个非常有用的工具。 1. Google 地图…

    2023年2月27日
    11500
  • 工作进度管理软件有哪些

    盘点国内外8款优秀的工作任务进度管理软件:1.产品研发进度管理-PingCode;2.项目任务进度管理-Worktile;3.工作任务进度管理-进度猫;4.个人/小团队进度管理-Teambition;5.工程项目进度管理-Primavera P6;6.缺陷跟踪管理-Jira等。 一、工作进度管理软件…

    2023年3月15日
    3500
  • 持续交付流水线的作用是什么

    持续交付流水线的作用包括以下几点:1、接管和屏蔽底层环境的差异;2、自动化流程引擎;3、挂载执行分层分级的流水线任务。流水线也是“持续稳定可重复的提供高质量的价值”的重要不可或缺的实践,服务于持续交付。 持续交付流水线的作用包括接管和屏蔽底层环境的差异、自动化流程引擎以及挂载执行分层分级的流水线任务…

    2022年10月17日
    12300
  • 如何搭建自己的ai 知识库

    建立知识库的步骤:一、明确知识库的目的和范围;二、选择适合的知识库工具;三、制定知识库管理规范和流程;四、收集和整理知识库内容;五、建立知识库文档结构和索引;六、推广和使用知识库。在建立知识库之前,需要确定知识库的建立目的和覆盖范围。 一、明确知识库的目的和范围 在建立知识库之前,需要确定知识库的建…

    2023年3月30日
    500
  • 服务管理是什么

    服务管理是面临服务竞争社会而产生的一种新的管理模式。它虽然已经历长达30多年的研究过程,虽然在产生的必要性及其概念,特征和一些理论探讨方面取得了众多研究成果,但是至今尚未形成完整的学科体系。 服务管理是面临服务竞争社会而产生的一种新的管理模式。它虽然已经历长达30多年的研究过程,虽然在产生的必要性及…

    2022年11月6日
    3600
  • 企业邮箱怎么申请

    企业邮箱的申请平台有很多,本文将介绍:一、阿里企业邮箱;二、QQ邮箱;三、网易企业邮。申请阿里企业邮箱的步骤:1、点击立即注册;2、输入信息;3、点击同意并注册。 一、阿里企业邮箱 1、点击立即注册 在阿里企业邮箱中,找到右上角的立即注册按钮,点击它。 2、输入信息 在新界面中,输入账号的名称、密码…

    2023年3月25日
    300
  • 计算机移动应用开发跟软件技术有啥区别

    计算机移动应用开发跟软件技术的区别有:1、作为科学领域时的区别;2、作为专业学科时的区别。作为科学领域时的区别是指,计算机移动应用开发更加注重于在移动设备平台上进行开发,而软件技术是开发和实施各种软件系统的技术。 一、计算机移动应用开发跟软件技术有啥区别 计算机移动应用开发跟软件技术这两个名词既可以…

    2023年3月30日
    1000

发表回复

登录后才能评论
联系我们
站长微信
站长微信
分享本页
返回顶部