并发前置知识一:线程基础

发布时间:2024年01月11日

一、通用的线程生命周期:“五态模型”

IMG_0021 2.JPG

二、java线程有哪几种状态?

  1. New:创建完线程
  2. Runable:start(),这里的Runnable包含操作的系统的Running(运行状态)和Ready(上面的可运行状态)
  3. Blocked:等待一个排它锁,当java线程在调用阻塞api时(阻塞读取文件),是否会转到Blocked那?在jvm层面,java线程状态是不会发生变化,还是Runnable,因为jvm不关心操作系统调度,在jvm看来,等待cpu使用权(操作系统层面处于可运行状态)和等待i/o(操作系统此时处于休眠状态)没有区别,都是在等待某个资源,所以都归于Runnable状态。只有在等待获取隐式锁的时候,才会进入到阻塞状态。
  4. Waiting(无限期等待):等待其他线程显示的唤醒,否则不会被分配cpu时间片

image.png

  1. Time Waiting(限期等待):无需等待其他线程显式的唤醒,在一定时间之后会被系统自动唤醒

image.png
调用Thread.sleep方法会使得线程进入限期等待状态,常常用“使一个线程睡眠”描述
调用object.wait(xxx) 方法使得线程进入限期等待,常常用“挂起一个线程”描述

睡眠和挂起是一个动作,阻塞和等待是一个状态
阻塞和等待的区别在于,阻塞是一个被动的,它是在等待一个排它锁;等待(无论来自于sleep还是wait)是一个主动的,通过主动调用方法进入的

  1. Terminated: 1、线程正常执行完 2、线程被interrupt(这里是不建议使用stop的,如果用stop杀死线程的话,如果线程持有Lock锁,就不会调用unlock也就不会释放锁)。

另外:
Blocking、Waiting、Timed_Waiting这几种状态可以统一理解为休眠状态,当线程处于这几种状态时,线程是没有cpu的使用权的。

三、java线程之间状态切换是什么样的?

image.png

四、创建线程有哪些方式?

  1. 实现Runnable接口,然后传到Thread作为参数
  2. 实现Callable接口,然后将Callable接口传入到FutureTask中,再将FutureTask传入到Thread作为参数

image.png
Callable实现返回值,futureTask实现异步

  1. 直接继承Thread,重新run方法

五、interrupt方法

interrupt作为一种线程交互的方式,相比stop温柔多了。对于被interrupt的线程,如果想要接收通知,有以下2种方式:

  1. 异常

当线程处于 Waiting、Timed_Waiting状态时,如果其他线程调用线程A的interrupt方法,会使线程A返回到Runnable状态,同时线程A的代码会触发InterruptException异常。我们在调用wait、join、sleep方法,都能看的这些方法都会throws interruptException,这个异常的触发条件就是其他线程调用该线程的interrupt方法

当线程A处于Runnable,并且阻塞在java.io.channels.interruptiableChannel上时,如果其他线程调用A的interrupt方法,线程A会触发java.nio.channels.ClosedByinterruptException;而阻塞在java.nio.channels.Selector上时,如果其他线程调用线程A的interrupt方法,线程A会立即返回

  1. 主动检测

通过主动检测 thread.isInterupted方法,来判断自己是否被中断了

文章来源:https://blog.csdn.net/LittleStar_Cao/article/details/135540941
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。