深入理解Java虚拟机【十二】Java内存模型与线程【12.4】Java与线程

12.4 Java与线程(P455 ~ P461)

    并发是一种概念,而多线程则是实现并发的具体方式。实现并发的方式很多,例如多进程,多线程只是其中之一。

12.4.1 线程的实现(P455 ~ P458)
内核线程实现(1:1实现)

    内核线程实现是依赖操作系统的多线程实现方式。在内核线程实现中,线程的本质是轻量级进程,操作系统通过内核线程(由操作系统直接控制的线程)来支持轻量级进程。

  • 优点: 由操作系统实现,无需关注线程的生命周期,实现更加简便;
  • 缺点: 消耗操作系统内核资源,支持的内核程数量有限;
  • 特点:1:1实现,一个内核线程支持一个轻量级进程(线程)。
用户线程实现(1:N实现)

    用户线程实现与操作系统无关,是依赖用户空间线程库的多线程实现方式。在用户线程实现中,线程的本质就是用户线程,个人对用户空间线程库并不了解,但无需在意,知道与操作系统无关即可。

  • 优点:不消耗操作系统内核资源,支持数量庞大的线程数量;
  • 缺点:需自实现线程的生命周期,使得用户线程程序会相当复杂;
  • 特点:1:N实现,一个CPU同时支持多个用户线程。
混合实现(N:M实现)

    顾名思义,混合实现即是混合了内核线程实现及用户线程实现的多线程实现方式。以轻量级进程作为桥梁,沟通内核线程与用户线程,既可以使用操作系统控制线程的生命周期及处理器映射,又可以发挥用户线程消耗资源少,数量大的优点。

    混合实现中,线程的本质是内核线程与用户线程的综合体(轻量级进程是两者沟通的桥梁)。因为一个用户线程可被多个内核线程支持,而一个内核线程也可支持多个用户线程,因此该实现也被称为N:M实现。

Java线程实现

    支持目前,Java线程实现采用内核线程实现(1:1实现)。因为采用内核线程实现,所以Java线程也具有内核线程的相关优缺点,这已经不太符合现如今“高并发”的网络环境,因此Java也在努力升级Java线程实现,尝试引入用户线程。

12.4.2 Java线程调度(P458 ~ P460)

    线程有协同式调度及抢占式调度两种调度方式,Java线程使用的是抢占式调度

协同式调度

    协同式调度实现简单,但稳定性极差。协同式调度由线程本身来实现调度,线程的执行时间由自己控制(即线程执行完所有的任务后再把硬件资源交给其他线程)。协同式调度的稳定性非常差,设想如果线程异常,使得其无法交出硬件资源,将导致整个程序无法进行,在早期的单核物理机中甚至会导致整个系统崩溃。

抢占式调度

    抢占式调度由操作系统实现,稳定性强。与协同式调度不同,抢占式调度下由操作系统控制线程的执行时间(即硬件资源的占用时间),并且在线程异常情况下也不会造成严重的稳定性问题,因为操作系统会将硬件资源交出去。

    可以通过设置线程的优先级来建议操作系统优先执行该线程,这种建议并不是必然有效的,就类似于我们可以建议JVM进行GC,但JVM是否会执行是未知的。Java共有10种线程优先级,但因为操作系统的多样化,这些优先级在映射到操作系统层面时可能会出现层级重叠(例如某操作系统只有5种线程优先级,那部分Java线程优先级在映射时必然会被映射为同一操作系统系统优先级),并且因为系统本身的优化策略,优先级可能会出现被修改的情况。

    public static void main(String[] args) {
        Thread thread = new Thread();
        // 设置线程优先级。
        thread.setPriority(Thread.MAX_PRIORITY);
    }
12.4.3 状态转换(P460 ~ P461)

    Java定义有6种线程状态,具体如下。

  1. 新建(New):创建后尚未启动的线程处于这种状态;
  2. 运行(Runnable):包括操作系统线程状态中的(Running)和(Ready),也就是处于此状态的的线程有可能正在执行,也有可能正在等待着操作系统为它分配执行时间;
  3. 无限期等待(Waiting):处于该状态的线程不会被分配处理器执行时间,他们要等待被其它线程显式唤醒;
  4. 限期等待(Timed Waiting):处于该状态的线程也不会被分配处理器执行时间,不过无需等待被其它线程显式唤醒,在一定时间之后它们会由系统自动唤醒;
  5. 阻塞(Blocked):线程被阻塞了,“阻塞状态”与“等待状态”的区别是“阻塞状态”在等待获取到一个排它锁,这个事件将在另外一个线程放弃的这个锁的时候发生;而“等待状态”则是在等待一段时间,或者唤醒动作的发生。在程序等待进入同步区域的时候,线程将进入这种状态;
  6. 结束(Terminated):表示该线程已经执行完毕。

    无限期等待与限期等待的真正差别不在于等待时间。从名称上看,两者的直接差异在于等待时间的有无限期上,但现实上如果不给Thread::sleep()方法设定时间,同样是“无限期等待”的语义。两者的真正区别在于被唤醒的方式。无限期等待线程只能被另一个Java线程唤醒,而限期等待线程会被操作系统唤醒,想必已经有人猜到,这实际与线程的调度方式有所关系。

【上篇】《深入理解Java虚拟机【十二】Java内存模型与线程【12.3】Java内存模型》
【下篇】《深入理解Java虚拟机【十二】Java内存模型与线程【12.5】Java与协程》

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

说淑人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值