java并发编程基础

目录

 

线程的生命周期:线程有6种状态:(NEW,RUNNABLE,BLOCKED,WAITING,TIME_WAITING,TERMINATED)

​ 线程的启动

线程的终止

为什么要复位

线程的终止原理 


线程的生命周期:线程有6种状态:(NEW,RUNNABLE,BLOCKED,WAITING,TIME_WAITING,TERMINATED)

NEW:初始状态,线程被构建,但是还没有调用start方法

RUNNABLE:运行状态,java把操作系统中的就绪和运行两种状态同意称为“运行中”

BLOCKED:阻塞状态:表示线程 进行等待状态:也就是因为某种原因放弃了CPU的使用权,阻塞分为几种情况:

  1.    等待阻塞:运行的线程执行wait()方法,jvm会把当前的线程放入等待队列
  2.  同步阻塞:运行的线程获取对象的同步锁时,若该同步锁被其他线程锁占用了,那么jvm会把当前的线程放入到锁池中
  3. 其他阻塞:运行的线程执行Thread.sleep().或者t.join方法,或者发出i/o请求时,jvm会把当前的线程设置为阻塞状态,当sleep结束,join线程终止,io处理完毕则线程恢复

 IME_WAITING:超时等待状态,超时以后自动返回
TERMINATED:终止状态,表示当前线程执行完毕

 线程的启动

 调用start()方法去启动一个线程,当 run 方法中的代码执行完毕以后,线程的生命周期也将终止。调用 start 方法的语义是当前线程告诉 JVM,启动调用 start 方法的线程,

我们看到调用 start 方法实际上是调用一个 native 方法start0()来启动一个线程,首先 start0()这个方法是在Thread 的静态块中来注册的,代码如下

{registerNatives()} 

 registerNatives 的 本 地 方 法 的 定 义 在 文 件Thread.c,Thread.c 定义了各个操作系统平台要用的关于线程的公共数据和操作
在hostpot的源码中的

start0() , 实 际 会 执 行JVM_StartThread 方法,这个方法是干嘛的呢? 从名字上来看,似乎是在 JVM 层面去启动一个线程,如果真的是这样,那么在 JVM 层面,一定会调用 Java 中定义的 run 方法:

实际会去调用平台创建线程的方法Threa::start(),来创建线程,然后就是线程的启动,会调用平台的线程启动的方法javaThread::run(),才是去开始一个真正的线程,直接代码调用run()只是一个不相当于一个普通的方法调用

线程的终止

线程的终止,并不是简单的调用 stop 命令去。虽然 api 仍然可以调用,但是和其他的线程控制方法如 suspend、resume 一样都是过期了的不建议使用,就拿 stop 来说,stop 方法在结束一个线程时并不会保证线程的资源正常释放,因此会导致程序可能出现一些不确定的状态。要优雅的去中断一个线程,在线程中提供了一个 interrupt方法
interrupt 方法
当其他线程通过调用当前线程的 interrupt 方法,表示向当前线程打个招呼,告诉他可以中断线程的执行了,至于什么时候中断,取决于当前线程自己。线程通过检查资深是否被中断来进行相应,可以通过isInterrupted()来判断是否被中断这种通过标识位或者中断操作的方式能够使线程在终止时 有机会去清理资源,而不是武断地将线程停止,因此这种 终止线程的做法显得更加安全和优雅。

Thread.interrupted

上面的案例中,通过 interrupt,设置了一个标识告诉线程 可 以 终 止 了 , 线 程 中 还 提 供 了 静 态 方 法 Thread.interrupted()对设置中断标识的线程复位。比如在 上面的案例中,外面的线程调用 thread.interrupt 来设置中 断标识,而在线程里面,又通过 Thread.interrupted 把线 程的标识又进行了复位 

其他的线程复位

除了通过 Thread.interrupted 方法对线程中断标识进行复 位 以 外 , 还 有 一 种 被 动 复 位 的 场 景 , 就 是 对 抛 出 InterruptedException 异 常 的 方 法 , 在 InterruptedException 抛出之前,JVM 会先把线程的中断 标识位清除,然后才会抛出 InterruptedException,这个时 候如果调用 isInterrupted 方法,将会返回 false

为什么要复位

Thread.interrupted()是属于当前线程的,是当前线程对外 界中断信号的一个响应,表示自己已经得到了中断信号, 但不会立刻中断自己,具体什么时候中断由自己决定,让 外界知道在自身中断前,他的中断状态仍然是 false,这就 是复位的原因。

线程的终止原理
 

thread.interrupt()方法做了什么事情 调用了 interrupt0(),这个方法在前面分析 start 方法的时候见过,是一个 native 方法,这里就不再重 复贴代码了,同样,我们找到 jvm.cpp 文件,找到 JVM_Interrupt 的定义,所以对于不同的操作平台,线程的调度方式都是不一 样的。set_interrupted(true)实际上就是调用 osThread.hpp 中的 set_interrupted()方法,在 osThread 中定义了一个成员属 性 volatile jint _interrupted; 通过上面的代码分析可以知道,thread.interrupt()方法实际 就是设置一个 interrupted 状态标识为 true、并且通过 ParkEvent 的 unpark 方法来唤醒线程。

1. 对于 synchronized 阻塞的线程,被唤醒以后会继续尝试 获取锁,如果失败仍然可能被 park

2. 在调用 ParkEvent 的 park 方法之前,会先判断线程的中 断状态,如果为 true,会清除当前线程的中断标识

3. Object.wait 、 Thread.sleep 、 Thread.join 会 抛 出 InterruptedException

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值