Java的多线程
  • 线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单位。一个进程可以有一个或多个线程,Java的多线程是通过JMM(共享内存模型)来实现的。
  • 大部分的操作系统都是利用时间片轮转的抢占式调度方式,线程需要利用操作系统的调度算法在用户态和内核态来回切换,线程的切换是非常浪费资源的,所以Java的线程池在工作中才那么常用,也是面试中无法绕过的坎。
  • 程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口——轻量级进程(Lightweight Process,LWP),轻量级进程就是我们通常意义上所讲的线程,也被叫做用户线程。
线程的实现模型
  • 一对一模型

一个用户线程对应一个内核线程,如果是多核的 CPU,那么线程之间是真正的并发。

缺点:

内核线程的数量有限,一对一模型使用的用户线程数量有限制。
内核线程的调度,上下文切换的开销较大(虽然没有进程上下文切换的开销大),导致用户线程的执行效率下降。

  • 多对一模型

多个用户线程映射到一个内核线程上,线程间的切换由用户态的代码来进行。用户线程的建立、同步、销毁都是在用户态中完成,不需要内核的介入。因此多对一的上下文切换速度快很多,且用户线程的数量几乎没有限制。

缺点:

若一个用户线程阻塞,其他所有线程都无法执行,此时内核线程处于阻塞状态。
处理器数量的增加,不会对多对一模型的线程性能造成影响,因为所有的用户线程都映射到了一个处理器上。

  • 多对多模型

结合了一对一模型和多对一模型的优点,多个用户线程映射到多个内核线程上,由线程库负责在可用的可调度实体上调度用户线程。这样线程间的上下文切换很快,因为它避免了系统调用。但是增加了系统的复杂性。

优点:

一个用户线程的阻塞不会导致所有线程的阻塞,因为此时还有别的内核线程被调度来执行;
多对多模型对用户线程的数量没有限制;
在多处理器的操作系统中,多对多模型的线程也能得到一定的性能提升,但提升的幅度不如一对一模型的高。

Java实现多线程

在Java中创建线程的方式有很多种,那么就写一个平时工作中最常见的方式,也就是上面提到的线程池。

    public ExecutorService asyncExecutor() {return new ThreadPoolExecutor(100, 200, 10,TimeUnit.SECONDS, new LinkedBlockingQueue<>(100), new NamedThreadFactory(ASYNC_NAME + "-"));}

使用方法如下:

    @Resource(name = "asyncExecutor")private ExecutorService executor;executor.execute();
Golang的协程
  • 和Java不同的是协程不需要通过共享内存来通信,而是通过通信来共享内存。
  • 协程也并不是Golang提出来的,协程是一种编程思想,并不局限于特定的语言。Go、Python、Kotlin都可以在语言层面上实现协程,Java 也可以通过扩展库的方式间接支持协程。协程比线程更加轻量级,可以由程序员自己管理的轻量级线程,对内核不可见。
  • Golang为构建并发程序的基本代码块是:协程 (goroutine) 与通道 (channel)。他们需要语言,编译器,和 runtime 的支持。
协程的原理

当出现IO阻塞的时候,由协程的调度器进行调度,通过将数据流立刻yield掉(主动让出),并且记录当前栈上的数据,阻塞完后立刻再通过线程恢复栈,并把阻塞的结果放到这个线程上去跑,这样看上去好像跟写同步代码没有任何差别,这整个流程可以称为coroutine,而跑在由coroutine负责调度的线程称为Fiber。比如Golang里的 go关键字其实就是负责开启一个Fiber,让func逻辑跑在上面。

由于协程的暂停完全由程序控制,发生在用户态上;而线程的阻塞状态是由操作系统内核来进行切换,发生在内核态上。
因此,协程的开销远远小于线程的开销,也就没有了 ContextSwitch 上的开销。

假设程序中默认创建两个线程为协程使用,在主线程中创建协程ABCD…,分别存储在就绪队列中,调度器首先会分配一个工作线程A执行协程A,另外一个工作线程B执行协程B,其它创建的协程将会放在队列中进行排队等待。

当协程A调用暂停方法或被阻塞时,协程A会进入到挂起队列,调度器会调用等待队列中的其它协程抢占线程A执行。当协程A被唤醒时,它需要重新进入到就绪队列中,通过调度器抢占线程,如果抢占成功,就继续执行协程A,失败则继续等待抢占线程。

总结
  • Java 在 Linux 操作系统下使用的是用户线程+轻量级线程,一个用户线程映射到一个内核线程,线程之间的切换就涉及到了上下文切换。所以在 Java 中并不适合创建大量的线程,否则效率会很低。
  • 对Java而言,操作系统会分配一块默认1M大小的栈,如果深度递归可能出现栈大小不足,但是如果一次性分配更大的内存又有可能出现浪费的现象;协程开始的时候也会分配一定大小的内存区域,一般只有2K,和线程的栈一样,协程的栈存储的也是局部变量,但是不同的是协程的栈的大小是不固定的,是可以根据需要自动调整大小的,最大甚至可以达到1G,所以灵活性非常好。
  • 上面也说到Java线程需要在用户态和内核态来回切换,这样子就会很浪费资源;但是协程只是用户态。
  • 协程适合于阻塞IO,对于CPU计算密集型的协程也不能很好解决。

本文只是从原理、应用场景来分析一下线程和协程的区别。

浅析Java的线程和Golang的协程相关推荐

  1. golang异步协程调度原理

    golang异步协程调度 在1.14的go版本中,官方通过加入信号来进行协程的调度,后续就都支持了这种异步协程抢占,避免了早起的考栈调度时来检查是否执行超时的逻辑.本文简单来对比这种实现的原理. 调度 ...

  2. 线程,进程,协程详细解释

    什么是进程和线程 进程是什么呢? 直白地讲,进程就是应用程序的启动实例.比如我们运行一个游戏,打开一个软件,就是开启了一个进程. 进程拥有代码和打开的文件资源.数据资源.独立的内存空间. 线程又是什么 ...

  3. golang goroutine协程运行机制及使用详解

    Go(又称Golang)是Google开发的一种静态强类型.编译型.并发型,并具有垃圾回收功能的编程语言.Go于2009年正式推出,国内各大互联网公司都有使用,尤其是七牛云,基本都是golang写的, ...

  4. k8s与监控--从telegraf改造谈golang多协程精确控制

    从telegraf改造谈golang多协程精确控制 前言 telegraf是infuxdb公司开源出来的一个基于插件机制的收集metrics的 项目.整个架构和elastic公司的日志收集系统极其类似 ...

  5. Golang的协程调度

    调度的基础,模型关系的映射 GPM模型: G,Goroutinue 被调度器管理的轻量级线程,goroutine使用go关键字创建 调度系统的最基本单位goroutine,存储了goroutine的执 ...

  6. Golang的协程调度器原理及GMP设计思想

    一.Golang"调度器"的由来? (1) 单进程时代不需要调度器 我们知道,一切的软件都是跑在操作系统上,真正用来干活(计算)的是CPU.早期的操作系统每个程序就是一个进程,知道 ...

  7. Python中的线程、进程、协程以及区别

    进程,是执行中的计算机程序.也就是说,每个代码在执行的时候,首先本身即是一个进程.一个进程具有:就绪,运行,中断,僵死,结束等状态(不同操作系统不一样). 运行中每个进程都拥有自己的地址空间.内存.数 ...

  8. Python 线程和进程和协程总结

    Python 线程和进程和协程总结 线程和进程和协程 进程 进程是程序执行时的一个实例,是担当分配系统资源(CPU时间.内存等)的基本单位: 进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其 ...

  9. Python之路,Day9 - 线程、进程、协程和IO多路复用

    参考博客: 线程.进程.协程: http://www.cnblogs.com/wupeiqi/articles/5040827.html http://www.cnblogs.com/alex3714 ...

  10. 教你打开线程、进程和协程的大门!

    作者 | 蓝  责编 | 张文 头图 | CSDN 下载自视觉中国 不知从几何起,可能是大三那年的操作系统考试,也可能是刚经历完的秋招,这些概念总是迷迷糊糊,可能自己回答的和其他人的答复也差不多,并没 ...

最新文章

  1. python3自动释放线程_Python3高级特性:并发
  2. Docker中运行EOS FOR MAC
  3. android 上下滚动文字_android高仿今日头条富文本编辑(发布文章)
  4. ionic上拉加载-下拉刷新
  5. 阿里数据库内核月报:2015年11月
  6. 基于时序数据库做监控,这里有超流行的开源方案
  7. bzoj 1753: [Usaco2005 qua]Who's in the Middle【排序】
  8. [MEGA DEAL]完整的Java捆绑包(96%折扣)
  9. java private是什么_java private 干什么用
  10. epplus word html,EPPlus简介
  11. 竞拍网站服务器配置,GOM引擎新区竞拍脚本,GOM传奇服务端设置竞拍的方法和教程...
  12. 用VBS脚本实现软件定条件开启
  13. Arduino控制PS2无线手柄
  14. 苹果x与苹果xs的区别_x和XS的区别到底在哪里,我来告诉你
  15. js获取剪切板文字图片方法
  16. 亚瑟阿伦的三十六个问题。
  17. 从图片到涂鸦:高品质涂鸦的自动生成
  18. 群体药动学药效学模型
  19. 支付宝电脑网页支付接口的调用
  20. 人工智能实战2019 第五次作业 焦宇恒 16721088

热门文章

  1. 永磁无刷直流电机的分类与区别
  2. 奶奶说标题不能起的太长要不然会有憨憨跟着读之Linux简述及常用命令
  3. ico生成工具ico制作工具ico在线制作
  4. xp怎么看自己计算机密码,如何找回Windows XP系统密码啊?
  5. 基于5片FPGA处理的PCIE光纤传输硬件加速卡
  6. csv文件行数超过软件上限解决方案
  7. 数据分析之参数检验与非参数检验
  8. 触动精灵 获取外网IP
  9. 使用Cisco Packet Tracer之图解无线网络全网互联
  10. 两台(或多台)电脑怎么实现文件共享