并发-线程运行原理剖析

线程运行原理

栈和栈帧
  • 每个栈由多个栈帧组成,对应着每次方法调用所占用的内存
  • 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法
线程上下文切换(Thread Context Switch)

因为以下一些原因导致cpu不再执行当前的线程,转而执行另一个线程的代码

  • 线程的cpu时间片用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了sleep、yield、wait、join、park、synchronized、lock等方法程序

当Context Switch发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,java中就是用程序计数器完成,它记住下一条jvm指令的执行地址

常见方法

start和run
  • 直接调用run方法是主线程中执行了run,没有启动新的线程
  • 使用start是启动新的线程,通过新的线程间接执行run中的代码
sleep
  • 调用sleep会让当前线程从Running进入Timed Waiting状态
  • 其他线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出IntertuptedException
  • 睡眠结束后的线程未必会立刻得到执行(要等任务调度器分配时间片)
  • 建议使用TimeUnit的sleep代替Thread的sleep来获得更好的可读性
yield
  • 调用yield会让当前线程从Running进入Runnable就绪状态,然后调度执行其他线程
  • 具体的实现依赖于操作系统的任务调度器
sleep和yield区别
  • 就绪状态还是有机会让任务调度器调度的,但是time wating不会
  • sleep有一段休眠时间,yield没有参数,也就是没有等待时间
线程优先级
  • 线程优先级会提示调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽视它
  • 如果cpu比较忙,那么优先级高的线程会获得更多的时间片,但cpu闲时,优先级几乎没有作用
  • setPriority()设置线程优先级
join
  • 等待线程运行结束,谁调用它就等待谁
interrupt
  • 打断处于阻塞的线程(sleep、wait、join的线程)

    • 打断这些线程会清空打断状态
  • 打断正常运行的线程,不会清空打断状态

    Thread t1 = new Thread(()->{
        while (true){
            boolean interrupted = Thread.currentThread().isInterrupted();
            if (interrupted){
                log.info("被打断了,优雅的退出循环");
                break;
            }
        }
    },"t1");
    
    t1.start();
    TimeUnit.SECONDS.sleep(1);
    log.info("interrupt...");
    t1.interrupt();
    
  • 打断park线程,不会清空打断状态

守护线程

只要等其他的非守护线程运行结束了,即使守护进程的代码没有执行完,也会强制结束

用setDaemon()设置守护进程,垃圾回收器就是一种守护进程,java应用结束了,垃圾回收线程也会停止

线程状态

操作系统看,有五种状态:

在这里插入图片描述

  • 【初始状态】:仅在语言层面创建了线程对象,还未与操作系统线程关联
  • 【可运行状态】:(就绪状态)指该线程已经被创建(与操作系统线程关联),可以由CPU调度执行
  • 【运行状态】:指获取了CPU时间片运行中的状态
    • 当CPU时间片用完,会从运行状态转换为可运行状态,会导致线程的上下文切换
  • 【阻塞状态】:
    • 如果调用了阻塞API,如BIO读取文件,这时线程实际不会用到CPU,会导致线程上下文切换,进入阻塞状态
    • 等BIO操作完毕,会由操作系统唤醒阻塞的线程,进入可运行状态,等待下一次CPU分配时间片
    • 与可运行状态的区别是,对阻塞状态的线程来说只要它们一直不唤醒,调度器就一直不会考虑调度它们
  • 【终止状态】:表示线程已经执行完毕,生命周期已经结束

Java API层面,有六种状态:
在这里插入图片描述

  • 【NEW】:线程刚刚被创建,还没有调用start()方法
  • 【RUNNABLE】:调用了start方法后,这个状态覆盖了操作系统层面的可运行状态、运行状态、阻塞状态(由于BIO造成的线程阻塞,在java中无法区分,仍然认为是可运行的)
  • 【BLOCKED】【WAITING】【TIMED_WAITING】:都是Java API层面对阻塞状态的细分
  • 【TERMINATED】:当线程代码运行结束
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

涛堆堆

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

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

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

打赏作者

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

抵扣说明:

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

余额充值