Java 并发编程实战
王宝令
资深架构师
72486 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 51 讲
学习攻略 (1讲)
Java 并发编程实战
15
15
1.0x
00:00/00:00
登录|注册

44 | 协程:更轻量级的线程

结构化程序设计
风险
实现同步非阻塞
实现Thread-Per-Message模式
简单创建协程
协程比线程轻量得多
协程切换成本更低
协程在用户态调度
线程在内核态调度
代码质量
思维模式
易用性
go语句
示例代码
Kotlin
Lua
Python
Golang
空间维度
操作系统角度
总结
结构化并发编程
Golang中的协程
支持协程的语言
轻量级的线程
协程

该思维导图由 AI 生成,仅供参考

Java 语言里解决并发问题靠的是多线程,但线程是个重量级的对象,不能频繁创建、销毁,而且线程切换的成本也很高,为了解决这些问题,Java SDK 提供了线程池。然而用好线程池并不容易,Java 围绕线程池提供了很多工具类,这些工具类学起来也不容易。那有没有更好的解决方案呢?Java 语言里目前还没有,但是其他语言里有,这个方案就是协程(Coroutine)。
我们可以把协程简单地理解为一种轻量级的线程。从操作系统的角度来看,线程是在内核态中调度的,而协程是在用户态调度的,所以相对于线程来说,协程切换的成本更低。协程虽然也有自己的栈,但是相比线程栈要小得多,典型的线程栈大小差不多有 1M,而协程栈的大小往往只有几 K 或者几十 K。所以,无论是从时间维度还是空间维度来看,协程都比线程轻量得多。
支持协程的语言还是挺多的,例如 Golang、Python、Lua、Kotlin 等都支持协程。下面我们就以 Golang 为代表,看看协程是如何在 Golang 中使用的。

Golang 中的协程

在 Golang 中创建协程非常简单,在下面的示例代码中,要让 hello() 方法在一个新的协程中执行,只需要go hello("World") 这一行代码就搞定了。你可以对比着想想在 Java 里是如何“辛勤”地创建线程和线程池的吧,我的感觉一直都是:每次写完 Golang 的代码,就再也不想写 Java 代码了。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

近年来,越来越多的编程语言开始支持协程,这项并发编程技术的易用性成为了关注焦点。协程作为一种轻量级线程,相较于传统多线程具有更低的创建和切换成本,因此在解决并发问题时具有优势。目前,Golang、Python、Lua、Kotlin等语言均支持协程,而在Java领域,Loom项目的目标也是支持协程。协程的简单使用方式以及能够简化并发编程复杂性的特点,使其能够很好地实现Thread-Per-Message模式,并将异步模式转换为同步模式,实现同步非阻塞的程序设计。然而,需要注意的是,过度使用协程可能会导致程序结构混乱,违背结构化程序设计原则。因此,在并发编程中,需要谨慎使用协程,避免程序变得难以理解和维护。在编写代码时,可读性是至关重要的,好的代码应该根植于广大群众之中,为人民群众服务。因此,在编写代码时,应该用大众、普通的思维模式去写代码,而不是炫耀自己的各种设计能力。总之,协程作为一项并发编程技术,解决了并发工具的易用性问题,但在使用时需要注意保持代码的可读性和结构化。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 并发编程实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(34)

  • 最新
  • 精选
  • 高源
    王老师请教一下现在多数互联网公司后台都采用go语言开发了,学习go语言是不是也很有必要了,还是根据应用场景或者工作的实际情况来看啊。

    作者回复: 看你时间了,最好要实践,如果公司没这样的项目,建议参与一个质量不错的开源的项目,一定要实践

    2019-06-08
    6
    31
  • 海水
    王老师好,有个问题请教下,公司支付接口调用的三方接口,这个三方接口秒级的耗时,如果想提高并发单单提高tomcat线程数或者该用异步sevlet是不是解决不了问题?我感觉这种情况应该是不是应该用协程比如go routine这样的才能解决这样的并发场景?毕竟三方接口的耗时省不了

    作者回复: 你可以试试基于netty的http客户端,再加上异步servlet试试。这俩必须一起用才有效果

    2019-06-08
    3
    17
  • 艾斯曼
    ”在 Java 里使用多线程并发地处理 I/O,基本上用的都是异步非阻塞模型,这种模型的异步主要是靠注册回调函数实现的,那能否都使用同步处理呢?显然是不能的。因为同步意味着等待,而线程等待,本质上就是一种严重的浪费。“ 老师您好,Java中Netty使用的是非阻塞+IO多路复用,这个应该属于同步IO还是异步IO?我的理解是这个属于同步IO,异步IO在windows上是IOCP,在linux其实AIO相关的API对socket不支持样,所以linux都是使用epoll+非阻塞的同步IO。不知道我这样理解是否正确?谢谢

    作者回复: 在操作系统层面看,你的理解是对的。语言,框架层面还会再封装,这个封装会改变同步,异步。底层都是epoll,封装后可能是异步形式,也可能是同步形式

    2020-03-22
    3
    13
  • DFighting
    很赞同老师最后提到的软件产品开发,任何需要协作和迭代的事物都需要遵从基本的规范和规则,不然再牛叉的技术只能孤芳自赏,给产品带来的只有灾难。

    作者回复: 👍

    2019-10-17
    9
  • windy
    关注老师专栏有一段时间了,老师讲解通俗易懂,涉猎的知识面很广。讲解某个知识点首先说明由来,背后理论,然后展开脉络进行剖析,如何应用到实践中,学以致用。在此送上感谢!

    作者回复: 客气了,你觉得还有用,我心里就踏实了,我就怕讲不明白

    2019-06-10
    9
  • the geek
    哈哈,本来是上来复习一下,结果新冒出了一章46/45

    作者回复: 早知道这么想,我就收工了😂😂

    2019-06-08
    6
  • Jxin
    我也把代码可读性排在第一位。我的目的是降低他人加入开发的成本。从长远看,这会让软件更具活力和可能性。毕竟虽然暂时来看为了可读性可能会损失一些性能和时间。但从长远来看,加入的人越多,节省别人的时间就越多,总会超过我的投入。而性能,随着业务的发展,后续可能能写出更贴合业务场景的优化方案。更何况,习惯后,写高可读性的代码并不会多花我时间。

    作者回复: 👍

    2019-06-17
    3
  • Liam
    cosocket的非阻塞体现在哪里呢,是说receive等方法是非阻塞方法吗?

    作者回复: 是的

    2019-06-09
    3
    3
  • zhangtnty
    王老师好,很赞同总结中讲的代码质量的看法。我认为好的项目不仅功能强大, 代码结构清晰非常重要, 好的代码结构一定和业务如出一辙,而不是过多的花式代码,总给人一种练手的感觉。

    作者回复: 代码结构和业务匹配太重要了👍

    2019-06-08
    3
  • Geek_b38ae5
    同步是针对几个线程,才会有协调。 而阻塞是针对单个线程把线程,放进线程阻塞队列里面吗?

    作者回复: 阻塞本质上是操作系统将线程状态变成阻塞,剥夺线程的CPU使用权,线程只有被唤醒(状态变为可执行)后,操作系统才会重新调度执行他

    2021-05-09
    2
收起评论
显示
设置
留言
34
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部