Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

19 | 如何用协程来优化多线程业务?

Kilim协程框架实现源码
Java多线程实现源码
通信载体(Mailbox)
任务调度器(Scheduler)
任务上下文(Fiber)
任务载体(Task)
内核线程
用户线程
轻量级进程
内核线程
Java中的协程
协程设计方式
协程优势
性能对比
生产者和消费者案例
核心组件
协程挂起和唤醒
协程调度器
协程概念
N:M线程模型
N:1线程模型
1:1线程模型
思考题
总结
协程与线程的性能比较
Kilim协程框架
协程的实现原理
线程实现模型
Java协程优化多线程业务

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

你好,我是刘超。
近一两年,国内很多互联网公司开始使用或转型 Go 语言,其中一个很重要的原因就是 Go 语言优越的性能表现,而这个优势与 Go 实现的轻量级线程 Goroutines(协程 Coroutine)不无关系。那么 Go 协程的实现与 Java 线程的实现有什么区别呢?

线程实现模型

了解协程和线程的区别之前,我们不妨先来了解下底层实现线程几种方式,为后面的学习打个基础。
实现线程主要有三种方式:轻量级进程和内核线程一对一相互映射实现的 1:1 线程模型、用户线程和内核线程实现的 N:1 线程模型以及用户线程和轻量级进程混合实现的 N:M 线程模型。

1:1 线程模型

以上我提到的内核线程(Kernel-Level Thread, KLT)是由操作系统内核支持的线程,内核通过调度器对线程进行调度,并负责完成线程的切换。
我们知道在 Linux 操作系统编程中,往往都是通过 fork() 函数创建一个子进程来代表一个内核中的线程。一个进程调用 fork() 函数后,系统会先给新的进程分配资源,例如,存储数据和代码的空间。然后把原来进程的所有值都复制到新的进程中,只有少数值与原来进程的值(比如 PID)不同,这相当于复制了一个主进程。
采用 fork() 创建子进程的方式来实现并行运行,会产生大量冗余数据,即占用大量内存空间,又消耗大量 CPU 时间用来初始化内存空间以及复制数据。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java如何用协程来优化多线程业务?本文通过对比Java和Go语言的线程实现模型,深入探讨了协程的实现原理和在Java中的应用。刘超介绍了Go语言的协程在提升性能方面的优势,以及Java线程实现模型的区别。他详细解释了1:1、N:1和N:M线程模型的特点,以及Java和Go语言在Linux下的线程实现方式。文章还介绍了协程的实现原理,指出协程是一种轻量级的线程,通过调度器实现挂起和唤醒,避免了同步资源竞争带来的CPU上下文切换,适合于I/O密集型的应用。对于Java语言目前不支持协程的问题,作者提到了Kilim协程框架,通过该框架可以在Java中使用协程。他详细介绍了Kilim框架的核心组件,包括任务载体、任务上下文、任务调度器和通信载体,以及如何在Java中使用该框架。通过一个简单的生产者和消费者的案例,对比了协程和线程的性能,发现在有严重阻塞的场景下,协程的性能更胜一筹。文章总结了协程的设计方式极大地提高了线程的使用率,同时指出Java的协程设计还有很长的路要走。文章内容深入浅出,为读者提供了对协程优化多线程业务的深入理解和实践指导。

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

全部留言(37)

  • 最新
  • 精选
  • 帽子丨影
    文中提到协程有个队列,最终还是需要主线程来调度执行。那是不是有点类似线程池。主线程是Worker线程,每一个协程就是一个Task。只不过主线程执行到的某个Task阻塞时会去执行下一个Task。

    作者回复: 对的,这样理解很清晰

    2019-08-16
    14
  • 小橙橙
    老师,以后的JAVA版本是不是也会自带协程功能?

    作者回复: 是的,Java未来的三个主要项目之一Loom项目 引入了被称为 fibers 的新型轻量级用户线程,甲骨文公司 Loom 项目技术负责人 Ron Pressler 在 QCon 伦敦 2019 大会上指出:“利用 fibers,如果我们确保其轻量化程度高于内核提供的线程,那么问题就得到了解决。大家将能够尽可能多地使用这些用户模式下的轻量级线程,且基本不会出现任何阻塞问题”。 具体的可以阅读以下openjdk官网链接: https://cr.openjdk.java.net/~rpressler/loom/Loom-Proposal.html

    2019-07-05
    2
    14
  • 课前思考及问题 1:协程是啥? 2:协程更轻量怎么体现,它轻量在哪里? 3:为什么多协程没有高并发的问题? 4:协程真这么优秀,为啥没有全面支持或使用?换言之实现协程需要什么代价? 昨晚休息的太晚了,今天脑袋晕晕的,状态不佳感觉学完还是回答不好,课前的思考题。先跳过,回头再看一下。 课后思考及问题 1:协程与线程最大的不同就是,线程是通过共享内存来实现数据共享,而协程是使用了通信的方式来实现了数据共享,主要就是为了避免内存共享数据而带来的线程安全问题。 这里的通信方式具体指什么?它比共享内存通信的方式还要快嘛?每个协程间都需要建立这种通信方式不耗资源不影响性能嘛? 2:而 Go 语言是使用了 N:M 线程模型实现了自己的调度器,它在 N 个内核线程上多路复用(或调度)M 个协程,协程的上下文切换是在用户态由协程调度器完成的,因此不需要陷入内核,相比之下,这个代价就很小了。 协程的执行不需要CPU?若需要,就会存在切入切出,协程的上下文切换怎么能在用户态全部完成,这个没有理解?

    作者回复: 1、这里说的通信方式是指协程间的通信方式,是通过数据共享来实现的,不存在线程安全问题; 2、需要CPU,协程可以更充分的利用好CPU,不会来回切换资源。

    2019-09-10
    2
    3
  • 学无涯
    老师,读了今天的内容,我理解的意思是: 1.因为每个轻量级线程都有一个内核线程支持,而java中,每个用户线程对应一个轻量级线程,可以看作用户线程和支持轻量级线程的内核线程是一对一的,所以就说java线程模型是用户线程和内核线程一对一。 2.那这里轻量级线程属于内核线程吗,我看文中说的是由内核线程clone而来的,那它算内核线程吗? 请老师解答一下!

    作者回复: 1、对的 2、属于用户线程,与内核线程一对一映射

    2019-07-02
    3
  • 晓晨同学
    请问老师,上面说N:1这种线程模型是当某个用户线程使用内核线程阻塞的时候会使整个进程下的所有用户线程阻塞,那我想为什么不能像N:M线程模型一样当某个用户线程阻塞时就挂起来从而去调度其他的用户线程呢

    作者回复: 可以,只是实现成本的问题

    2019-11-13
    2
  • Ericens
    老师,请教个关于协程与线程的疑问。比如,a协程调用socket. read(),此时数据没有准备好,则继续调度b协程。 把协程换成线程,上面这个过程哪个更加轻量?协程还是线程? 我理解这个过程涉及的过程如下,都一样。 1.都有系统调用read(),从用户态切换到了内核态, 2.都有上下文切换。(不同协程的寄存器,和不同线程的寄存器) 3. 都要执行任务调度。协程调度或者线程调度。 那协程到底轻量在哪?

    作者回复: 协程更轻量级,协程是线程的子集,所以不会存在线程间的上下文切换,而仅仅是通过调度器来完成调度的。

    2019-10-11
    2
    2
  • 葛阳
    "相对于 fork() 系统调用创建的线程来说,LWP 使用 clone() 系统调用创建线程,该函数是将部分父进程的资源的数据结构进行复制,复制内容可选,且没有被复制的资源可以通过指针共享给子进程。因此,轻量级进程的运行单元更小,运行速度更快。LWP 是跟内核线程一对一映射的,每个 LWP 都是由一个内核线程支持。" -- 这句话是不是有毛病,一会儿"进程"一会儿"线程"

    作者回复: 这里的进程应该理解为线程,因为在unix编程中,通常以进程来代表线程的

    2020-04-27
    1
  • 慎独
    老师,协程在高并发系统中使用过吗?

    作者回复: 协程可以胜任高并发场景,不过目前没有在线上的Java项目使用过协程

    2019-12-04
    1
  • neohope
    1. Java框架的话,Kilim有一段时间没有更新了,最近Quasar好像流行一些。 2. JVM里,可以混用Kotlin;或者是混用Scala+akka。 3. 未来版本的JDK也会逐步支持协程,但现在的实验版本好像只是在Linux下支持的比较好。 4 .不过说实话,现在的netty框架,在一定意义上工作原理和协程也有一些相似之处。

    作者回复: netty在处理同步业务场景下,特别是业务处理比较耗时的场景下,并发处理能力有限。

    2019-11-22
    1
  • deepz
    协程被暂停,那下次再执行怎么知道执行到哪里了呢?是程序计数器记录了吗? 追求高吞吐量的系统,协程是不是就不能帮上忙了?

    作者回复: 对的,有个任务调度器。如果是IO密集型的场景,协程会更又优势。

    2020-02-24
收起评论
显示
设置
留言
37
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部