《四》多线程基础——Java线程生命周期及转换

news2024/9/22 21:23:09

Java并发编程系列文章
《一》多线程基础——Java线程与进程的基本概念
《二》多线程基础——Java线程入门类和接口
《三》多线程基础——Java线程组和线程优先级
《四》多线程基础——Java线程生命周期及转换
《五》多线程基础——Java线程间的通信(互斥与协作)
《六》实际应用——如何优雅的关闭线程
《七》实际应用——生产者与消费者模型

  并发编程(多线程)一直以来都是程序员头疼的难题。曾经听别人总结过并发编程的第一原则,那就是不要写并发程序,哈哈哈。后来发现,这样能够显著提高程序响应和吞吐量的利器,哪还能忍得住不会用呢?
  整理出《Java并发编程系列文章》,共计7篇,与君共勉。


《四》多线程基础——Java线程生命周期及转换

  • 1、Java线程生命周期
    • 1.1、Java线程的6个状态
      • (1)NEW(初始化)
      • (2)RUNNABLE(可运行或运行中)
      • (3)BLOCKED(阻塞)
      • (4)WAITING(等待)
      • (5)TIMED_WAITING(超时等待)
      • (6)TERMINATED(终止)
    • 1.2、Java线程状态的转换
      • (1)BLOCKED与RUNNABLE状态的转换
      • (2)WAITING状态与RUNNABLE状态的转换
      • (3)TIMED_WAITING与RUNNABLE状态转换
      • (4)线程中断


1、Java线程生命周期

1.1、Java线程的6个状态

// Thread.State 源码
public enum State {
 NEW,
 RUNNABLE,
 BLOCKED,
 WAITING,
 TIMED_WAITING,
 TERMINATED;
}

(1)NEW(初始化)

private void testStateNew() {
 Thread thread = new Thread(() -> {});
 System.out.println(thread.getState()); // 输出 NEW 
}

  只创建了线程⽽并没有调⽤start()⽅法,此时线程处于NEW状态。

关于start()的两个引申问题

  1. 反复调⽤同⼀个线程的start()⽅法是否可⾏?
    start()源码中有⼀个threadStatus的变量的判断,如果不等于0,就会直接抛出异常的。因为调用一次start()后,threadStatus值会改变,所以不能。
  2. 假如⼀个线程执⾏完毕(此时处于TERMINATED状态),再次调⽤这个线程的start()⽅法是否可行?
    因为处于TERMINATED状态的线程,threadStatus不等于0,所以不能。
    RUNNABLE,

(2)RUNNABLE(可运行或运行中)

  Java线程的RUNNABLE状态其实是包括了传统操作系统线程的readyrunning两个状态的。

(3)BLOCKED(阻塞)

  阻塞状态。处于BLOCKED状态的线程正等待锁的释放以进⼊同步区。

(4)WAITING(等待)

  等待状态。处于等待状态的线程变成RUNNABLE状态需要其他线程唤醒。

调⽤如下3个⽅法会使线程进⼊等待状态:
Object.wait():使当前线程处于等待状态直到另⼀个线程唤醒它;
Thread.join():等待线程执⾏完毕,底层调⽤的是Object实例的wait⽅法;
LockSupport.park():除⾮获得调⽤许可,否则禁⽤当前线程进⾏线程调度。

(5)TIMED_WAITING(超时等待)

  超时等待状态。线程等待⼀个具体的时间,时间到后会被⾃动唤醒。

调⽤如下⽅法会使线程进⼊超时等待状态:
Thread.sleep(long millis):使当前线程睡眠指定时间;
Object.wait(long timeout):线程休眠指定时间;
Thread.join(long millis):等待当前线程最多执⾏millis毫秒,如果millis为0,则会⼀直执⾏;
LockSupport.parkNanos(long nanos): 除⾮获得调⽤许可,否则禁⽤当前线程进⾏线程调度指定时间;
LockSupport.parkUntil(long deadline):同上,也是禁⽌线程进⾏调度指定时间;

(6)TERMINATED(终止)

  终⽌状态。此时线程已执⾏完毕。

1.2、Java线程状态的转换

在这里插入图片描述

(1)BLOCKED与RUNNABLE状态的转换

  处于BLOCKED状态的线程是因为在等待锁的释放。假如这⾥有两个线程a和b,a线程提前获得了锁并且暂未释放锁,此时b就处于BLOCKED状态。我们先来看⼀个例⼦:

public void blockedTest() {
    Thread a = new Thread(new Runnable() {
        @Override
        public void run() {
            testMethod();
        }
    }, "a");
    Thread b = new Thread(new Runnable() {
        @Override
        public void run() {
            testMethod();
        }
    }, "b");
    a.start();
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 输出?
    System.out.println(b.getName() + ":" + b.getState()); // 输出?
}
// 同步⽅法争夺锁
private synchronized void testMethod() {
    try {
        Thread.sleep(2000L);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

  除了a、b线程,还有⼀个main线程。线程启动后执⾏run⽅法还是需要消耗⼀定时间的。不打断点的情况下,上⾯代码中都应该输出RUNNABLE
  具体来说,main线程只保证了a,b两个线程调⽤start()⽅法(转化为RUNNABLE状态),还没等两个线程真正开始争夺锁,就已经打印此时两个线程的状态(RUNNABLE)了。
  我们把上⾯的改动⼀下:

     ······
    a.start();
    Thread.sleep(1000L); // 需要注意这⾥main线程休眠了1000毫秒,⽽testMethod()⾥休眠了
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 输出?
    System.out.println(b.getName() + ":" + b.getState()); // 输出?

  由于main线程休眠,所以线程a的run()⽅法跟着执⾏,线程b再接着执⾏。在线程a执⾏run()调⽤testMethod()之后,线程a休眠了2000ms(注意这⾥是没有释放锁的),main线程休眠完毕,接着b线程执⾏的时候是争夺不到锁的,所以这⾥输出:

a:TIMED_WAITING
b:BLOCKED

(2)WAITING状态与RUNNABLE状态的转换

  转换图我们知道有3个⽅法可以使线程从RUNNABLE状态转为WAITING状态。我们主要说一下Object.wait()Thread.join()

Object.wait()
调⽤wait()⽅法前线程必须持有对象的锁。
调⽤wait()⽅法时,会释放当前的锁,直到有其他线程调⽤notify()/notifyAll()⽅法唤醒等待锁的线程。
需要注意的是,其他线程调⽤notify()⽅法只会随机唤醒单个等待锁的线程。调⽤notifyAll()⽅法唤醒所有等待锁的线程之后,也不⼀定会⻢上把时间⽚分给刚才放弃锁的那个线程,具体要看系统的调度。

Object.wait()
调⽤join()⽅法不会释放锁,会⼀直等待当前线程执⾏完毕(转换为
TERMINATED状态)。

我们把上面的例子改动一下:

    ······
    a.start();
    a.join();
    b.start();
    System.out.println(a.getName() + ":" + a.getState()); // 输出 TERMINATED
    System.out.println(b.getName() + ":" + b.getState());

  要是没有调⽤join⽅法,main线程不管a线程是否执⾏完毕都会继续往下⾛。a线程启动之后⻢上调⽤了join⽅法,这⾥main线程就会等到a线程执⾏完毕,所以这⾥a线程打印的状态固定是TERMIATED
⾄于b线程的状态,有可能打印RUNNABLE(尚未进⼊同步⽅法),也有可能打印TIMED_WAITING(进⼊了同步⽅法)。

(3)TIMED_WAITING与RUNNABLE状态转换

  TIMED_WAITINGWAITING状态类似,只是TIMED_WAITING状态等待的时间是指定的。

Thread.sleep(long)
使当前线程睡眠指定时间,并不会释放锁。时间到后,线程会重新进⼊RUNNABLE状态。

Object.wait(long)
wait(long)⽅法使线程进⼊TIMED_WAITING状态。这⾥的wait(long)⽅法与
⽆参⽅法wait()相同的地⽅是,都可以通过其他线程调⽤notify()或notifyAll() ⽅法来唤醒。
不同的地⽅是,经过指定时间 long之后它会⾃动唤醒,线程会重新进⼊RUNNABLE状态。

Thread.join(long)
join(long)使当前线程执⾏指定时间,并且使线程进⼊TIMED_WAITING状
态。

(4)线程中断

  在某些情况下,我们在线程启动后发现并不需要它继续执⾏下去时,需要中断线程。⽬前在Java⾥还没有安全直接的⽅法来停⽌线程。需要注意,通过中断操作并不能直接终⽌⼀个线程,⽽是通知需要被中断的线程⾃⾏处理。

简单介绍下Thread类⾥提供的关于线程中断的⼏个⽅法:
Thread.interrupt():中断线程。这⾥的中断线程并不会⽴即停⽌线程,⽽是设 置线程的中断状态为true(默认是flase);
Thread.interrupted():测试当前线程是否被中断。线程的中断状态受这个⽅法的影响,意思是调⽤⼀次使线程中断状态设置为true,连续调⽤两次会使得这 个线程的中断状态重新转为false;
Thread.isInterrupted():测试当前线程是否被中断。与上⾯⽅法不同的是调⽤ 这个⽅法并不会影响线程的中断状态。

  在线程中断机制⾥,当其他线程通知需要被中断的线程后,线程中断的状态被设置为true,但是具体被要求中断的线程要怎么处理,完全由被中断线程⾃⼰⽽定,可以在合适的实际处理中断请求,也可以完全不处理继续执⾏下去。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/69244.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Git统计代码行数;Java实现统计代码行数,忽略空行、注释行

前言 某天,产品叫我算下某个项目的代码行数,我一愣,这怎么统计?总不可能一个文件一个文件算吧?后面我找了下,git是可以统计提交到仓库的所有的代码的,不过有个问题,就是假如有些文件…

在STM32F103C8T6上使用RT_Thread Nano移植控制台和Finsh

一、移植环境: 开发环境:Keil MDK 5.33 硬件平台:STM32F103C8T6 RT_Thread版本:RT-Thread Nano V3.1.5 二、在RT-Thread Nano V3.1.5添加uart控制台 1.需要在rtconfig.h开启以下两个宏 1)#define RT_USING_CONSO…

ITK (1)窗宽窗位的意义与设置

背景与意义 医学图像与传统可视化图像相比,其具有更大的“灰度”范围。如,普通图像(灰度图像)的灰度范围一般是256级(即图像中最亮的点的灰度值定义为0,最亮的定义为255,也就是2^8,…

【图像处理OpenCV(C++版)】——2.1 深入理解OpenCV之Mat类及相关成员函数

前言: 😊😊😊欢迎来到本博客😊😊😊 🌟🌟🌟 本专栏主要结合OpenCV和C来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快…

【论文阅读31】《OptCuts: Joint Optimization of Surface Cuts and Parameterization》

目录 一些疑惑 0 引言 1 introduction 2 related work 2.1 parameterization with fixed connectivity 2.2 Separate Cut Computation 3 problem statement ​编辑​ 3.1 数学形式1 3.2 数学形式2 3.3 能量函数 3.3.1 接缝线长度(归一化)&am…

程序员们,你会考虑使用中文编程吗?

众所周知,编程语言有一条无形的“鄙视链”。 Java和C#相互不服,并且看不起写Python的,Python看不起PHP,PHP看不起前端。而中文编程就在这个语言“鄙视链”的底端艰难生存。 有人对中文编程嗤之以鼻,相比于“人生苦短…

免费网课题库系统接口

免费网课题库系统接口 本平台优点:免费查题接口搭建 多题库查题、独立后台、响应速度快、全网平台可查、功能最全! 1.想要给自己的公众号获得查题接口,只需要两步! 2.题库:题库后台http://daili.jueguangzhe.cn/ 题…

[附源码]计算机毕业设计JAVA职业中介信息管理系统

[附源码]计算机毕业设计JAVA职业中介信息管理系统 项目运行 环境配置: Jdk1.8 Tomcat7.0 Mysql HBuilderX(Webstorm也行) Eclispe(IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持)。 项目技术: SSM my…

Java进阶——IO流(I)

文章目录IO流一、文件1.1、文件流1.2、常用的文件操作1.2.1、创建文件对象相关构造和方法1.2.2、获取文件的相关信息1.2.3、目录的操作和文件删除二、IO流原理及流的分类2.1、Java IO流的原理2.2、流的分类2.3、IO流常用的类2.3.1、InputStream:字节输入流FileInput…

SSH 远程连接协议详解

一、SSH 协议 1、SSH 协议简介 SSH全称是Secure Shell,SSH协议是基于应用层的协议,为远程登录会话和其他网络服务提供安全性的协议。 SSH使用最多的是远程登录和传输文件,实现此功能的传统协议都不安全(ftp、telnet等),因为它们使用明文传输数据,而SSH在传输过程中的…

【云原生.docker】docker部署Redis集群

1、镜像拉取 docker pull redis:5.0.5 2、容器启动 docker run -d --nameredis-6400 --net host --privilegedtrue -v /home/dev/toms/docker_redis/data/redis-6400:/data redis:5.0.5 --cluster-enabled yes --appendonly yes --port 6400 & docker run -d --nameredis-…

在抖音及一些直播上,如何进行违禁词在线检测呢?

本文首发于:行者AI谛听 随着直播行业的兴起,越来越多的网红主播纷纷加入,平台的审核能力也面临着巨大的挑战,相对于平台的严格监管,很多主播也需要进行深层学习,避免在直播中出行违规。 其实很多主播在直播…

2023最新SSM计算机毕业设计选题大全(附源码+LW)之java小型餐饮综合管理系统j1c7m

首先选择计算机题目的时候先看定什么主题,一般的话都选择当年最热门的话题进行组题,就比如说,今年的热门话题有奥运会,全运会,残运会,或者疫情相关的,这些都是热门话题,所以你就可以…

文档对象模型 (DOM) :初学者介绍和指南

果你已经使用JavaScript一段时间了,你可能相当熟悉DOM(文档对象模型)和CSSOM(CSS对象模型)脚本。除了 DOM 和 CSSOM 规范定义的接口之外,CSSOM 视图模块中还指定了方法和属性的子集,从而提供了用…

Vue3知识点之数据侦测

Vue 的核心之一就是响应式系统,通过侦测数据的变化,来驱动更新视图。 实现可响应对象的方式 通过可响应对象,实现对数据的侦测,从而告知外界数据变化。实现可响应对象的方式: getter 和 setterdefinePropertyProxy …

IB课程工具书单,助力你考高分

亚马逊汇总了近期最畅销的IB课程工具书单,该书单以购买量和评分进行综合排名。其中的许多书籍都是IBDP学生可选用的绝佳工具书!1、Physics for the IB Diploma Coursebook 这本书涵盖了IB 2016年首考的物理课程要求。这本课程手册的第六版针对IB物理教学…

写出go程序

1.安装go包 下载地址:https://golang.google.cn/dl/ 2.安装vscode 下载地址:https://code.visualstudio.com/ 安装好后 以打开文件夹形式打开.go文件。 该文件自己创建一个即可。

怎么视频提取音频文件?分享这3种简单实用的提取方法

不知道大家平时用手机刷视频的时候,会不会被一些好听的背景音乐给吸引了呢?这些背景音乐大多都是网友们自己合成导入视频上传的,可能在许多音乐平台都不能找到音源播放。遇到这样的情况,大家一定都很苦恼吧?但其实&…

Fluorescein(5-isomer)-DBCO,2054339-00-1,二苯基环辛炔-FITC(5-异构体)

一、理论分析: 中文名:二苯基环辛炔-FITC(5-异构体),二苯并环辛炔-荧光素(5-异构体) 英文名:DBCO-FITC(5-isomer),5-FITC-DBCO,Fluorescein(5-isomer)-DBCO CAS号:2054339-00-1 化学式&#xff…

遥感影像目标检测:从CNN(Faster-RCNN)到Transformer(DETR)实践技术应用

我国高分辨率对地观测系统重大专项已全面启动,高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成,将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB,遥感大数据时…