Java多线程(1)---多线程认识、四种创建方式以及线程状态
目录
前言
一.Java的多线程
1.1多线程的认识
1.2Java多线程的创建方式
1.3Java多线程的生命周期
1.4Java多线程的执行机制
二.创建多线程的四种方式
2.1继承Thread类
⭐创建线程
⭐Thread的构造方法和常见属性
2.2.实现Runnable接口
⭐创建线程
⭐使用lambda表达式创建
2.3实现Callable接口创建多线程
⭐线程的创建
⭐Callable接口的特点
2.4通过线程池创建多线程
⭐创建线程
🎁个人主页:tq02的博客_CSDN博客-C语言,Java,Java数据结构领域博主
🎥 本文由 tq02 原创,首发于 CSDN🙉
🎄 本章讲解内容:多线程的认识、创建方式、及其状态
🎥学习专栏: C语言 JavaSE MySQL基础
前言
在学习多线程之前,我们必须了解什么是线程?作用是什么?而线程的知识又与进程有关系,因此我们需要先了解进程再去了解线程,这样才能更好的学习到多线程的知识。本文只是多线程的一部分,多线程涉及的知识点很多很多,锁啊、线程安全啊、CAS等知识,需要耐心学习。
进程学习:http://t.csdn.cn/I4uDU
线程学习:http://t.csdn.cn/AxYac
一.Java的多线程
1.1多线程的认识
多线程,从字面上理解,就是从多个单线程一起执行多个任务。在Java 编程中,已经给多线程编程提供了内置的支持。多线程是多任务的一种特别的形式,但多线程使用了更小的cpu资源开销。 多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。
线程本身就是操作系统提供的概念,因此操作系统提供了一些API供程序员使用,而在Java中,也存在一些API供人们使用和编译。在Java标准库中Thread类就是用于多线程的创建。
注:创建多线程的方式不仅仅只有Thread类
1.2Java多线程的创建方式
Java语言中,目前可以创建多线程的方式有四种方式:
- 继承Thread类
- 实现Runnable接口
- 使用lambda表达式(基于Runnable接口搭配内部类的优化)
- 使用线程池
- 使用FutureTask类和Callable接口
以上的1、2、5方法可以搭配匿名内部类使用,而目前最为常用的方式有:实现Runnable接口、调用多线程池。
1.3Java多线程的生命周期

新建状态、可执行状态、执行状态以及死亡状态是每一个线程都会发生,而阻塞状态则是选择性发生,当需要阻塞时,使用sleep()、join()方法。
1.4Java多线程的执行机制
当Java程序运行时,先创建出一个进程,该进程里至少包含一个线程,主线程,就是负责执行main方法的线程。然后在mian()方法里创建出其他线程。我们主要学习的就是创建和使用线程。

注:一般情况下,主线程与子线程相互不影响,即子线程结束,主线程不一定结束;主线程结束,子线程不一定结束;主线程异常,子线程不一定异常;子线程异常,主线程不一定异常。但当设置守护线程等特殊操作时,主线程与子线程会发生相互影响。
二.创建多线程的四种方式
2.1继承Thread类
⭐创建线程
使用Thread类创建线程有2种方式,最基本的实现多线程方式,就是创建一个类继承Thread类,然后再实例化该类。可实例化多个线程。
1.继承Thread类创建一个线程
class MyThread extends Thread {@Overridepublic void run() {System.out.println("这里是线程运行的代码");}
}public class Text{public static void main(String[] args) {//创建MyThread实例MyThread t1=new MyThread();//调用start方法启动线程t1.start();}
}
注:继承Thread类需要重写run()方法,而调用的是start()方法,而不是run()方法,start()是启动线程,而run()则是执行方法。
2.匿名内部类创建 Thread 子类对象
// 使用匿名类创建 Thread 子类对象
Thread t1 = new Thread() {@Overridepublic void run() {System.out.println("使用匿名类创建 Thread 子类对象");}
};//启动线程t1.start();
注:该方法不需要继承其他类,而是直接实例化Thread类和使用匿名内部类。
⭐Thread的构造方法和常见属性
Thread构造方法:
| 构造方法 | 解释 |
| Thread() | 创建线程 |
| Thread(Runnable 对象名) | 使用Runnable对象创建线程 |
| Thread(String 线程名) | 创建线程对象,并命名 |
| Thread(Runnable 对象名,String 线程名) | 使用Runnable对象创建线程对象,并命名 |
常见属性:
| 属性 | 获取方法 |
| ID | getId() |
| 名称 | getName() |
| 状态 | getState() |
| 优先级 | getPriority() |
| 是否有后台线程 | isDaemon() |
| 是否存活 | isAlive() |
| 是否中断 | isInterrupted() |
ID 是线程的唯一标识,不同线程不会重复
名称是各种调试工具用到
其中重要的是前台和后台线程:
- 前台线程,会影响到进程结束,如果前台进程没有执行完毕,进程不会结束
- 后台线程,也称守护线程,当主线程结束时,进程结束,后台线程无论是否还在执行也结束
Java多线程当中默认为前台线程,也可以通过setDaemon方法设置,false
存活是指线程是否执行结束。中断是指让正在执行的线程强行结束。类似循环的break;
2.2.实现Runnable接口
⭐创建线程
Runnable接口,将需要执行的线程放入其中,再通过Runnable和Thread配合,就可以进行线程的实现。而方法有2种。
第一种:创建Thread类实例,调用构造方法时,将Runnable对象传参
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("这里是线程运行的代码");}
}//创建Thread类实例
Thread t = new Thread(new MyRunnable());//调用start()方法t.start();
实现一个接口Runnable,然后重写run方法,再将Runnable实例化出的对象,放入Thread的构造函数Thread(Runnable 对象名),就可以实现线程的执行。
第二种:创建Thread类实例,搭配使用匿名内部类创建Runnable子类对象
// 使用匿名类创建 Runnable 子类对象
Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("使用匿名类创建 Runnable 子类对象");}
});
这种方法更为的简便,直接在匿名内部类当中重写run()方法,在run()方法内部写上需要执行的操作。
⭐使用lambda表达式创建
lambda表达式用于匿名内部类和接口的情况,而创建Thread类时,搭配匿名内部类创建了Runnable子类对象,因此可以使用lambda表达式的方法简化操作。
lambda表达式的学习:http://t.csdn.cn/VxRLy
代码示例:
// 使用 lambda 表达式创建 Runnable 子类对象
Thread t4 = new Thread(() -> {System.out.println("使用匿名类创建 Thread 子类对象");
});
如果看不懂lambda表达式,你就记住这是一种创建线程的方法,不去理解。
注:相比前几种创建方式,使用lambda表达式创建更为方便简单。
2.3实现Callable接口创建多线程
⭐线程的创建
Callable 是一个 interface . 使用时需要创建utureTask类的对象,相当于把线程封装了一个 "返回值". 方便程序猿借助多线程的方式计算结果.该方法是基于jdk5.0之后新增的方法,
方法步骤:
- 创建一个实现Callable接口的类。
- 在这个实现类中实现Callable接口的call()方法,并创建这个类的对象。
- 将这个Callable接口实现类的对象作为参数传递到FutureTask类的构造器中,创建FutureTask类的对象。
- 将这个FutureTask类的对象作为参数传递到Thread类的构造器中,创建Thread类的对象,并调用这个对象的start()方法。
- 在主线程中调用 futureTask.get() 能够阻塞等待新线程计算完毕. 并获取到 FutureTask 中的结
果。
代码示例:
Callable<Integer> callable = new Callable<Integer>() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 1000; i++) {sum += i;}return sum;}
};FutureTask<Integer> futureTask = new FutureTask<>(callable);Thread t = new Thread(futureTask);t.start();int result = futureTask.get();System.out.println(result);
⭐Callable接口的特点
- Callable 和 Runnable 相对, 都是描述一个 "任务". Callable 描述的是带有返回值的任务,Runnable 描述的是不带返回值的任务.
- Callable 通常需要搭配 FutureTask 来使用. FutureTask 用来保存 Callable 的返回结果. 因为
- Callable 往往是在另一个线程中执行的, 啥时候执行完并不确定.
- FutureTask 就可以负责这个等待结果出来的工作.
2.4通过线程池创建多线程
虽然创建销毁线程比创建销毁进程更轻量, 但是在频繁创建销毁线程的时候还是会比较低效.
线程池就是为了解决这个问题. 如果某个线程不再使用了, 并不是真正把线程释放, 而是放到一个 "池子"中, 下次如果需要用到线程就直接从池子中取, 不必通过系统来创建了.
⭐创建线程
1、线程池的使用,需要使用以下类:
- Executors 是一个工厂类, 能够创建出几种不同风格的线程池.
- ExecutorService 表示一个线程池实例.
- ExecutorService 的 submit 方法能够向线程池中提交若干个任务.
2、Executors 创建的几种风格线程池:
实例化一个线程池格式:ExecutorService pool = Executors.方法();
| 创建线程池种类 | 解释 |
| Executors.newFixedThreadPool(int Num threads) | 创建固定线程数的线程池 |
| Executors.newSingleThreadExecutor() | 创建只包含单个线程的线程池. |
| Executors.newCachedThreadPool() | 创建线程数目动态增长的线程池. |
| Executors.newScheduledThreadPool(int corePoolSize) | 设定延迟时间后执行命令,或者定期执行命令. 是 进阶版的 Timer. |
注:Executors 本质上是 ThreadPoolExecutor 类的封装
代码示例:
ExecutorService pool = Executors.newFixedThreadPool(10);pool.submit(new Runnable() {@Overridepublic void run() {System.out.println("hello");}
});//线程池使用结束之后需要使用shutdown()关闭pool.shutdown();
三.线程的状态
线程的状态是一个枚举类型 Thread.State,而线程的状态一共有6种,6种状态定义在Thread类的State枚举中。
- 初始状态(NEW):线程对象被创建但尚未调用start()方法。
- 就绪状态(RUNNABLE):线程处于可运行线程池中,等待被线程调度选中获取CPU的使用权。就绪状态分为两种情况,一是线程对象创建后,其他线程调用了该对象的start()方法,此时线程处于某个线程拿到对象锁、当前线程时间片用完调用yield()方法、锁池里的线程拿到对象锁后,这些线程也将进入就绪状态。
- 运行状态(RUNNABLE之RUNNING):线程正在被执行,具体来说就是线程获得了CPU的使用权。
- 阻塞状态(BLOCKED):线程阻塞于锁,即线程在等待获得对象锁。
- 等待状态(WAITING):线程需要等待其他线程做出一些特定动作,比如等待其他线程的通知或中断。
- 超时等待状态(TIMED_WAITING):与等待状态不同的是,超过指定时间后会自动返回。
- 终止状态(TERMINATED):线程的run()方法执行完成,或者主线程的main()方法执行完成,线程终止。终止状态的线程不能再被复生。如果在终止状态的线程上调用start()方法,会抛出java.lang.IllegalThreadStateException异常。
注:之前的 isAlive() 方法,可以认为是处于不是 NEW 和 TERMINATED 的状态都是活着
的
3.1状态的抽象说明
状态图:
- 初始状态(NEW):刚刚拿到银行卡
- 就绪状态(RUNNABLE):排队等待中
- 运行状态(RUNNABLE之RUNNING):开始与柜台人员进行交流取钱
- 阻塞状态(BLOCKED):阻塞了,相当于有人提前预约了取钱,你只能等待他结束
- 等待状态(WAITING):使用了wait()等待,例如柜台人员有一点事情,让你等到他回来
- 超时等待状态(TIMED_WAITING):使用了sleep(),柜台人员告诉了你等他多久;使用join()方法,就是你和你朋友同时在取钱,取钱到一半你说先停下来,我朋友那边取完了你再取。
多线程的概念、创建、状态的讲解本章已经结束了,而后期还有很多线程操作、线程安全、锁等知识,因此多线程是一个极为复杂并且重要的知识。
相关文章:
Java多线程(1)---多线程认识、四种创建方式以及线程状态
目录 前言 一.Java的多线程 1.1多线程的认识 1.2Java多线程的创建方式 1.3Java多线程的生命周期 1.4Java多线程的执行机制 二.创建多线程的四种方式 2.1继承Thread类 ⭐创建线程 ⭐Thread的构造方法和常见属性 2.2.实现Runnable接口 ⭐创建线程 ⭐使用lambda表达…...
搭建Django+pyhon+vue自动化测试平台
Django安装 使用管理员身份运行pycharm使用local 1 pip install django -i https://pypi.tuna.tsinghua.edu.cn/simple 检查django是否安装成功 1 python -m django --version 创建项目 1 1 django-admin startproject test cd 切换至创建的项目中启动django项目…...
CASAIM自动化平面度检测设备3D扫描零部件形位公差尺寸测量
平面度是表面形状的度量,指示沿该表面的所有点是否在同一平面中,当两个表面需要连接在一起形成紧密连接时,平面度检测至关重要。 CASAIM自动化平面度检测设备通过搭载领先的激光三维测头和智能检测软件自动获取零部件高质量测量数据…...
PostgreSql pg_ctl 命令
一、概述 控制 PostgreSQL 服务的工具。 二、语法 --初始化数据库实例 pg_ctl init[db] [-D datadir] [-s] [-o initdb-options]--启动数据库实例 pg_ctl start [-D datadir] [-l filename] [-W] [-t seconds] [-s] [-o options] [-p path] [-c]--停止数据库实例 pg_ctl sto…...
MySQL中的MVCC具体指的是什么?
在MySQL中,MVCC是指多版本并发控制(Multi-Version Concurrency Control)。它是一种用于处理并发读写操作的数据库事务管理技术。 MVCC通过在数据库中维护多个版本的数据来实现并发控制,每个事务在执行期间看到的数据版本是确定性…...
Docker网络模型详解
目录 一、Docker网络基础 1、端口映射 使用-P选项时Docker会随机映射一个端口至容器内部的开放端口 使用docker logs查看Nginx的日志 查看映射的随机端口范围 2、使用-p可以指定要映射到的本地端口。 Local_Port:Container_Port : 端口映射参数中指定了宿主…...
如何打造属于自己的个人IP?
在当今信息爆炸的时代,个人 IP 已经成为人们在网络世界中的独特标签。无论是在职场上、创业中,还是在社交生活中,拥有个人 IP 的人都能脱颖而出,吸引更多的关注和机会。那么,如何打造属于自己的个人 IP 呢?…...
全网最全最细的jmeter接口测试教程以及接口测试流程详解
一、Jmeter简介 Jmeter是由Apache公司开发的一个纯Java的开源项目,即可以用于做接口测试也可以用于做性能测试。 Jmeter具备高移植性,可以实现跨平台运行。 Jmeter可以实现分布式负载。 Jmeter采用多线程,允许通过多个线程并发取样或通过…...
【Linux命令200例】whereis用于搜索以及定位二进制文件
🏆作者简介,黑夜开发者,全栈领域新星创作者✌,阿里云社区专家博主,2023年6月csdn上海赛道top4。 🏆本文已收录于专栏:Linux命令大全。 🏆本专栏我们会通过具体的系统的命令讲解加上鲜…...
Elasticsearch:如何将整个 Elasticsearch 索引导出到文件 - Python 8.x
在实际的使用中,我们有时希望把 Elasticsearch 的索引保存到 JSON 文件中。在之前,我写了一篇管如何备份 Elasticsearch 索引的文章 “Elasticsearch:索引备份及恢复”。在今天,我们使用一种 Python 的方法来做进一步的探讨。你可…...
cmd 实现启动mysql时保留窗口
因为mysql启动后, 只有在任务管理器里能看到进程, 关的时候还需要找一下 所以基于 start cmd /k 命令实现了该效果 :: Author: admin :: Date: 2022-08-30 :: Version v1.2 :: ::启动 :: :: echo off::配置变量 set mysqlC:\mysql-5.7.38-winx64\bin\mysqld.exe::打印配置…...
JavaScript数据结构与算法——栈
文章目录 一、初始栈结构1.1 特性1.2 注意事项 二、栈结构的封装2.1 封装简单栈结构2.2 利用栈将十进制转二进制 一、初始栈结构 1.1 特性 类似于汉诺塔,后进先出,每次只能操作栈顶的元素。关键词:压栈、退栈 简单示意图: 1.…...
Elasticsearch分词详解:ES分词介绍、倒排索引介绍、分词器的作用、停用词
详见:https://blog.csdn.net/weixin_40612128/article/details/123476053...
SpringMVC组件
目录 1、简介 2、SpringMVC与Servlet的关系 3、struc2 4、RESTful 编程风格 5、工作流程 6、代码示例 6.1、导入坐标 provide 6.2、DispathcerServlet 🔺配置web.xml 初始化 优先级 ⭐ 6.3、Controller类及视图页面 6.4、配置注解 6.5、spring-mvc.xm…...
解决el-dialog弹出时,页面抖动,右侧会缩小的问题(即滚动条被遮罩层覆盖的问题)
问题描述: 在弹出el-dialog时,会发现弹出框弹出时,页面会抖动,滚动条被遮罩层覆盖直接没有滚动条了,导致页面缩小了几个像素点(滚动条的宽度);体验感不好,会影响到页面的…...
【Rust 基础篇】Rust 属性宏:定制你的代码
导言 Rust是一门现代的、安全的系统级编程语言,它提供了丰富的元编程特性,其中属性宏(Attribute Macros)是其中之一。属性宏允许开发者在代码上方添加自定义的属性,并对代码进行定制化处理。在本篇博客中,…...
2023-08-04力扣今日三题
链接: 剑指 Offer 35. 复杂链表的复制 题意: 如题 解: 看题研究了好一阵,指针map 实际代码: #include<bits/stdc.h> using namespace std; class Node { public:int val;Node* next;Node* random;Node(in…...
从HTTP代理到Socks5代理:网络安全与爬虫的进化之路
一、HTTP代理:简介与特点 HTTP代理是一种最早的代理技术,通过HTTP协议转发网络请求。它能够隐藏用户的真实IP地址,实现匿名访问,为爬虫应用提供了最基本的代理功能。 HTTP代理只支持TCP协议,对于实时数据传输和UDP协议…...
数学建模-元胞自动机
clc clear n 300; % 定义表示森林的矩阵大小 Plight 5e-6; Pgrowth 1e-2; % 定义闪电和生长的概率 UL [n,1:n-1]; DR [2:n,1]; % 定义上左,下右邻居 vegzeros(n,n); % 初始化表示森林的矩阵 imh ima…...
化学合成有机化学 | 逆合成分析软件/数据库汇总
化合物逆合成路线设计软件是一类用于辅助化学家设计化合物合成路线的工具。这些软件通常基于化学知识和反应数据库,能够根据目标化合物的结构和性质,提供合成路线的建议和优化方案。以下是一些常见的化合物逆合成路线设计软件: IntSynth&…...
变量 varablie 声明- Rust 变量 let mut 声明与 C/C++ 变量声明对比分析
一、变量声明设计:let 与 mut 的哲学解析 Rust 采用 let 声明变量并通过 mut 显式标记可变性,这种设计体现了语言的核心哲学。以下是深度解析: 1.1 设计理念剖析 安全优先原则:默认不可变强制开发者明确声明意图 let x 5; …...
.Net框架,除了EF还有很多很多......
文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...
ios苹果系统,js 滑动屏幕、锚定无效
现象:window.addEventListener监听touch无效,划不动屏幕,但是代码逻辑都有执行到。 scrollIntoView也无效。 原因:这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作,从而会影响…...
九天毕昇深度学习平台 | 如何安装库?
pip install 库名 -i https://pypi.tuna.tsinghua.edu.cn/simple --user 举个例子: 报错 ModuleNotFoundError: No module named torch 那么我需要安装 torch pip install torch -i https://pypi.tuna.tsinghua.edu.cn/simple --user pip install 库名&#x…...
#Uniapp篇:chrome调试unapp适配
chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器:Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
Java毕业设计:WML信息查询与后端信息发布系统开发
JAVAWML信息查询与后端信息发布系统实现 一、系统概述 本系统基于Java和WML(无线标记语言)技术开发,实现了移动设备上的信息查询与后端信息发布功能。系统采用B/S架构,服务器端使用Java Servlet处理请求,数据库采用MySQL存储信息࿰…...

