Java线程的基本概念和五种状态

1. 线程

1.1 创建线程

创建线程通常有以下三种方式:

实现 Runnable 接口,并重写其 run 方法:

public class J1_Method01 {public static void main(String[] args) {
        System.out.println("Main线程的ID为:" + Thread.currentThread().getId());
        Thread thread = new Thread(new CustomRunner());
        thread.start();}
}class CustomRunner implements Runnable {@Overridepublic void run() {
        System.out.println("CustomRunner线程的ID为:" + Thread.currentThread().getId());}
}

继承自 Thread 类,并重写其 run 方法:

public class J2_Method02 {public static void main(String[] args) {
        System.out.println("Main线程的ID为:" + Thread.currentThread().getId());
        CustomThread customThread = new CustomThread();
        customThread.start();}
}class CustomThread extends Thread {@Overridepublic void run() {
        System.out.println("CustomThread线程的ID为:" + Thread.currentThread().getId());}
}

以上两种方式都无法获取线程的返回值,如果想要获取线程的返回值,需要实现 Callable 接口:

public class J3_Method03 {public static void main(String[] args) throws ExecutionException, InterruptedException {
        Task task = new Task();
        FutureTask<Integer> futureTask = new FutureTask<>(task);new Thread(futureTask).start();
        System.out.println("获得线程返回值:" + futureTask.get());}
}class Task implements Callable<Integer> {@Overridepublic Integer call() {return 100;}
}
// 输出:
获得线程返回值:100

1.2 线程属性

编号 (ID) :用于标识线程的唯一编号,只读属性。

名称 (Name):用于定义线程名称,可读可写。

线程类别 (Daemon):通过线程的 `setDaemon(boolean on)` 方法进行设置,为 true 表示设置为守护线程,否则为用户线程。用户线程会阻止 Java 虚拟机正常停止,守护线程则不会。通常可以把一些不重要的线程设置为守护线程,比如监控其他线程状态的监控线程,当其他工作线程停止后,虚拟机就可以正常退出。

优先级 (Priority):Java 线程支持 1 到 10 十个优先级,默认值为 5 。Java 线程的优先级本质上只是给线程调度器一个提示信息,它并不能保证线程一定按照优先级的高低顺序运行,所以它是不可靠的,需要谨慎使用。在 Java 平台中,子线程的优先级默认与其父线程相同。

1.3 线程状态

Java 线程的生命周期分为以下五类状态:

RUNABLE:该状态包括两个子状态:READY 和 RUNING 。处于 READY 状态的线程被称为活跃线程,被线程调度器选中后才开始运行,转化为 RUNING 状态。

BLOCKED:一个线程发起一个阻塞式 IO 操作后(如文件读写或者阻塞式 Socket 读写),或者申请一个由其他线程持有的独占资源(比如锁)时,相应的线程就会处于该状态。

WAITING:线程处于无时间限制的等待状态。

TIMED_WAITING:有时间限制的等待状态,如果在指定时间内并没有执行的特定的操作,则该线程自动转换为 RUNABLE。

TERMINATED:`Thread.run()`正常返回或者由于抛出异常而提前终止,则对应的线程都会处于该终止状态。

各个状态之间的转换关系如下图:

1.4 线程终止

通常线程会随着代码的运行完成而终止,但如果你在线程中进行了死循环操作,此时就需要考虑如何安全地停止线程?虽然 Thread 类提供了 `stop()` 方法,但其已经被标识为废弃,因为 `stop()` 只是暴力的停止线程, 但此时线程中的操作仍可能处于中间状态,此时暴力地停止就可能会产生非预期的结果。想要安全的停止线程,可以通过改变终止标志位的方式来实现:

public class ThreadStop {private static volatile boolean stopFlag = true;public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {while (stopFlag) {try {
                    Thread.sleep(100);
                    System.out.println("持续输出");} catch (InterruptedException e) {
                    e.printStackTrace();}}});
        thread.start();
        Thread.sleep(3 * 1000);
        stopFlag = false;
        System.out.println("线程终止");}
}

1.5  线程中断

除了终止线程外,JDK 中提供了以下方法用于实现线程中断:

Thread.interrupt() :用于给目标线程设置中断标志位,但实际上并不能中断线程;

Thread.isInterrupted():通过检查中断标志位,判断当前线程是否被中断;

Thread.interrupted():用来判断当前线程的中断状态,同时会清除当前线程的中断标志位。

线程中断与线程终止的区别在于:线程中断只是告诉目标线程,我希望你停止运行,即设置标志位,而线程是否真的停止则是由其自行决定。示例如下:

/** 
 * interrupt() 只是设置中断标志位,并不能中断线程,所以子线程会持续打印
 */
public class J1_Interrupt {public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {while (true) {
                System.out.println("子线程打印");}});
        thread.start();
        Thread.sleep(10);
        thread.interrupt();}
}/**
 * isInterrupted() 用于检查当前线程是否存在中断标志位,配合interrupt()使用可以中断线程
 */
public class J2_IsInterrupted {public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {
                System.out.println("子线程打印");}});
        thread.start();
        Thread.sleep(10);
        thread.interrupt();}
}/**
 * interrupted() 用于判断当前线程的中断状态,并清除当前线程的中断标志位
 */
public class J3_Interrupted {public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {// 此时由于标志位被清除,此时子线程依然会持续打印while (!Thread.interrupted() || !Thread.currentThread().isInterrupted()) {
                System.out.println("子线程打印");}});
        thread.start();
        Thread.sleep(10);
        thread.interrupt();}
}

2. 基本概念

2.1 变量分类

状态变量 (State Variable) :即类的实例变量,非共享的静态变量。

共享变量 (Shared Variable) : 即可以被多个线程共同访问的变量。

2.2  竞态

如果多个线程并发的操作共享变量,并且这些操作不全是只读操作,那么它们彼此之间就会存在竞争,这种状态就称为竞态。由于竞态的存在,此时可能存在一个类在单线程的环境下能够正常运转,但在多线程的环境下却运行出错,此时就称这个类是线程不安全的。

public class J1_ThreadUnsafe {private static int i = 0;public static void main(String[] args) throws InterruptedException {
        IncreaseTask task = new IncreaseTask();
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);
        thread1.start();
        thread2.start();// 等待线程结束再打印返回值
        thread1.join();
        thread2.join();
        System.out.println(i); // 线程不安全,输出总是小于:200000}static class IncreaseTask implements Runnable {@Overridepublic void run() {for (int j = 0; j < 100000; j++) {inc();}}private void inc() {
            i++;}}
}

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

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

相关文章

公安涉密视频会议建设方案

公安涉密视频会议建设方案的制定需要考虑多方面因素。其一般是在复杂涉密网络环境中部署&#xff0c;怎样的内部保密部署方可保障涉密会议最大程度的加密进行呢&#xff1f;以下是从不同维度建设方案&#xff0c;可以根据实际应用场景进行相应的修改以及配置与之匹配的视频会议…

〔001〕虚幻 UE5 发送 get、post 请求、读取 json 文件

✨ 目录 🎈 安装 varest 扩展🎈 开启 varest 扩展🎈 发送 get 请求🎈 发送 post 请求🎈 读取 json 文件🎈 安装 varest 扩展 打开 虚幻商城,搜索 varest 关键字进行检索, varest 是一个 api 调用插件,支持 http/https 请求,也支持 json 文件的读取,最关键是该…

mermaid学习第一天/更改主题颜色和边框颜色/《需求解释流程图》

mermaid 在线官网&#xff1a; https://mermaid-js.github.io/ 在线学习文件&#xff1a; https://mermaid.js.org/syntax/quadrantChart.html 1、今天主要是想做需求解释的流程图&#xff0c;又不想自己画&#xff0c;就用了&#xff0c;框框不能直接进行全局配置&#xff0…

动态路由协议OSPF优化提速特性

1.OSPF协议通信过程与部署&#xff1b; 2.OSPF协议在项目上的应用场景&#xff1b; 3.OSPF有哪些优化特性&#xff1f; - OSPF - 开放式最短路径优先 - 一个动态路由协议 - 路由协议 - 理解魏 运行在路由器的一个软件 - 目的&#xff1a;为了帮助路由器和路由器彼…

Spring Boot 常见面试题

目录 1.Spring Boot 快速入门什么是 Spring Boot&#xff1f;有什么优点&#xff1f;Spring Boot 与 Spring MVC 有什么区别&#xff1f;Spring 与 Spring Boot 有什么关系&#xff1f;✨什么是 Spring Boot Starters?Spring Boot 支持哪些内嵌 Servlet 容器&#xff1f;如何设…

【LeetCode刷题-队列】--933.最近的请求次数

933.最近的请求次数 class RecentCounter {Queue<Integer> queue new LinkedList<>();public RecentCounter() {}public int ping(int t) {queue.offer(t);while(t - queue.peek() > 3000){queue.poll();}return queue.size();} }/*** Your RecentCounter obje…

游戏在小米设备上因自适应刷新率功能,帧率减半

1&#xff09;游戏在小米设备上因自适应刷新率功能&#xff0c;帧率减半 2&#xff09;Lua在计算时出现非法值&#xff0c;开启Debugger之后不再触发 3&#xff09;如何在Unity中实现液体蔓延的效果 这是第357篇UWA技术知识分享的推送&#xff0c;精选了UWA社区的热门话题&…

R语言gplots包的颜色索引表--全平台可用

R语言gplots包的颜色索引表–全平台可用

花了三年时间开发的开源项目,终于500 个 Star 了!快收藏

waynboot-mall 商城项目从疫情开始初期着手准备&#xff0c;到现在已经经过了 3 年多的时间&#xff0c;从项目初期到现在&#xff0c;一个人持续迭代&#xff0c;修复漏洞&#xff0c;添加功能&#xff0c;经历了前端开发工具从 vue2、vue-cli 切换到 vue3、vite 的转变&#…

JavaScript 自定义对象

<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>JS-定义对象</title> </head><body&g…

leetCode 137. 只出现一次的数字 II + 位运算 + 模3加法器 + 真值表(数字电路) + 有限状态机

给你一个整数数组 nums &#xff0c;除某个元素仅出现 一次 外&#xff0c;其余每个元素都恰出现 三次 。请你找出并返回那个只出现了一次的元素。你必须设计并实现线性时间复杂度的算法且使用常数级空间来解决此问题。 常规解法&#xff1a;哈希&#xff08;hash&#xff09; …

NSSCTF第十页(2)

[HNCTF 2022 WEEK3]ssssti 题目提示是jinja2模板 怎么感觉之前做过&#xff0c;看到了注入 随便进行一下注入&#xff0c;发现了过滤 大致的黑名单 " _ args -- 无法使用 request.args os -- 无法导入os 不允许post -- 无法使用 request.value 正常用的payloa…

什么是协议栈? 用户态协议栈设计(udp协议栈)

什么是协议栈呢&#xff1f; &#xff08;协议栈&#xff08;Protocol Stack&#xff09;是计算机网络和通信系统中的一个重要概念&#xff0c;它指的是一组协议层的层次结构&#xff0c;这些协议层一起协同工作&#xff0c;以便在不同计算机或设备之间实现数据通信和交换。每…

暴力递归转动态规划(十三)

题目 给定3个参数&#xff0c;N&#xff0c;M&#xff0c;K 怪兽有N滴血&#xff0c;等着英雄来砍自己 英雄每一次打击&#xff0c;都会让怪兽流失[0~M]的血量 到底流失多少&#xff1f;每一次在[0~M]上等概率的获得一个值 求K次打击之后&#xff0c;英雄把怪兽砍死的概率。 暴…

httpclient工具类(支持泛型转换)

1、网上搜到的httpclient工具类的问题&#xff1a; 1.1、如下图我们都能够发现这种封装的问题&#xff1a; 代码繁杂、充斥了很多重复性代码返回值单一&#xff0c;无法拿到对应的Java Bean对象及List对象集合实际场景中会对接大量第三方的OPEN API&#xff0c;下述方法的扩展…

zookeeper集群搭建

zookeeper&#xff08;动物园管理员&#xff09;是一个广泛应用于分布式服务提供协调服务Apache的开源框架 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它 负责存储和管理大家都关心的数据 &#xff0c;然 后 接受观察…

第 04 章_逻辑架构

第 04 章_逻辑架构 1. 逻辑架构剖析 1. 1 服务器处理客户端请求 那服务器进程对客户端进程发送的请求做了什么处理&#xff0c;才能产生最后的处理结果呢&#xff1f;这里以查询请求为 例展示&#xff1a; 下面具体展开看一下&#xff1a; 1.2 Connectors 1.3 第 1 层&…

Docker网络模式_Docker常用命令_以及Docker如何给运行的镜像内容连接互联网_Docker网络模式原理---Docker工作笔记004

然后我们来看一下docker的网络模式: 这个docker我们先看一下电脑上的网络,有两个,1个是lo是测试用的一个是enp0s3这个是我们以太网地址,然后我们去: 安装docker 安装后我们再去ip address可以看到多出来一个网络是docker0 这里ip地址是172.17.0.1这个是私有地址外部无法访问 这…

VSCode实用远程主机功能

作为嵌入式开发者&#xff0c;经常在各种系统平台或者开发工具之间切换&#xff0c;比如你的代码在Linux虚拟机上&#xff0c;如果不习惯在Linux下用IDE&#xff0c;那么我尝试将Linux的目录通过samba共享出来&#xff0c;在windows下用网络映射盘的方式映射出来&#xff0c;VS…

Python某建筑平台数据, 实现网站JS逆向解密

嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 环境使用: 首先我们先来安装一下写代码的软件&#xff08;对没安装的小白说&#xff09; Python 3.8 / 编译器 Pycharm 2021.2版本 / 编辑器 专业版是付费的 <文章下方名片可获取魔法永久用~> 社区版是免费的 模块…