【Java】创建多线程的四种方式
一、方式1:继承Thread类
步骤:
- 创建一个继承于Thread类的子类
- 重写Thread类的run()方法 ----> 此线程执行的操作声明在方法体中
- 创建当前Thread子类的对象
- 通过实例对象调用start()方法,启动线程 ----> Java虚拟机会调用run()方法
注意main()方法是主线程
1. 创建线程:
//自定义线程类
public class MyThread extends Thread {// 共享数据要放在run()方法外边才能被共享且声明为static,否则就是每个线程都会调用run()方法,都会单独拥有一个run()方法里的独享数据,而非共享数据//eg: static int trick = 100;//定义指定线程名称的构造方法public MyThread(String name) {//调用父类的String参数的构造方法,指定线程的名称super(name);}/*** 重写run方法,完成该线程执行的逻辑*/@Overridepublic void run() {// 执行的操作}
}
2. 调用线程:
public class TestMyThread {public static void main(String[] args) {//创建自定义线程对象1MyThread mt1 = new MyThread("子线程1");//开启子线程1mt1.start();//创建自定义线程对象2,分别创建对象开启线程,不可以数据共享,若要共享需要创建static变量MyThread mt2 = new MyThread("子线程2");//开启子线程2mt2.start();}
}
3. 创建Thread类的匿名子类的匿名对象
// 创建Thread类的匿名子类的匿名对象,并启动线程
new Thread(){public void run(){// 执行的操作}
}.strat(); // 启动线程
二、方式2:实现Runnable接口
- 创建一个实现Runnable接口的类
- 实现接口中的run()方法 ----> 线程执行的操作声明在此方法中
- 创建实例对象
- 将此对象作为参数传到Thread类的构造器中,创建Thread类的实例
- 通过Thread的实例对象调用strat()方法,启动线程 ----> Java虚拟机会调用run()方法
最终还是通过Thread实现的
1. 创建线程:
public class MyRunnable implements Runnable {// 共享数据要放在run()方法外边才能被共享,否则就是每个线程都会调用run()方法,都会单独拥有一个run()方法里的独享数据,而非共享数据//eg: int trick = 100;@Overridepublic void run() {// 执行的操作}
}
2. 调用线程
public class TestMyRunnable {public static void main(String[] args) {//创建自定义类对象 线程任务对象MyRunnable mr = new MyRunnable();//创建线程对象1Thread t1 = new Thread(mr, "长江1");t1.start();//创建线程对象2,注意两个线程传入的是同一个对象,可以实现数据共享Thread t2 = new Thread(mr, "长江2");t2.start();}
}
3. 创建Runnable接口的匿名子类的匿名对象
new Thread(new Runnable(){public run(){// 执行的操作}
}).start(); // 开启线程
三、继承Thread类 VS 实现Runnable接口
1. 共同点:
- 都是通过Thread类中定义的start()来启动线程。
- 都是通过Thread类或其子类的实例对象来创建线程。
2. 不同点:
- Thread是继承
- Runnable是实现
3. Runnable好处:
- 通过实现的方式,避免了类的单继承的局限性
- 自动共享数据,更适合处理有共享数据的业务逻辑
- 实现了逻辑代码(在run()方法中)和数据(在创建线程的方法中)的分离
四、Thread类常用方法和生命周期
1. 构造器
构造器 | 描述 |
---|---|
public Thread() | 分配一个新的线程对象。 |
public Thread(String name) | 分配一个指定名字的新的线程对象。 |
public Thread(Runnable target) | 指定创建线程的目标对象,它实现了Runnable接口中的run方法 |
public Thread(Runnable target,String name) | 分配一个带有指定目标新的线程对象并指定名字。 |
2. 常用方法——线程设置
构造器 | 描述 |
---|---|
public void run() | 此线程要执行的任务在此处定义代码。 |
public void start() | 导致此线程开始执行; Java虚拟机调用此线程的run方法。 |
public String getName() | 获取当前线程名称。 |
public void setName(String name) | 设置该线程名称。 |
public static Thread currentThread() | 返回对当前正在执行的线程对象的引用。在Thread子类中就是this,通常用于主线程和Runnable实现类 |
public static void sleep(long millis) | 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。 |
public static void yield() | 主动释放当前线程的执行权,一旦执行,就释放CPU的执行权,yield只是让当前线程暂停一下,让系统的线程调度器重新调度一次,希望优先级与当前线程相同或更高的其他线程能够获得执行机会,但是这个不能保证,完全有可能的情况是,当某个线程调用了yield方法暂停之后,线程调度器又将其调度出来重新执行。 |
3. 常用方法——阻塞线程
构造器 | 描述 |
---|---|
public final boolean isAlive() | 测试线程是否处于活动状态。如果线程已经启动且尚未终止,则为活动状态。 |
void join() | 阻塞其他线程,在线程a中通过线程b调用join(),意味着线程a进入阻塞状态,直到线程b执行结束,线程a才结束阻塞状态。等待该线程终止。 |
void join(long millis) | 阻塞其他线程,阻塞其他线程的时间最长为 millis 毫秒。如果millis时间到,将不再等待。 |
void join(long millis, int nanos) | 阻塞其他线程,阻塞其他线程的时间最长为 millis 毫秒 + nanos 纳秒。 |
public final void stop() | 已过时,不建议使用。强行结束一个线程的执行,直接进入死亡状态。run()即刻停止,可能会导致一些清理性的工作得不到完成,如文件,数据库等的关闭。同时,会立即释放该线程所持有的所有的锁,导致数据得不到同步的处理,出现数据不一致的问题。 |
void suspend() / void resume() | 这两个操作就好比播放器的暂停和恢复。二者必须成对出现,否则非常容易发生死锁。suspend()调用会导致线程暂停,但不会释放任何锁资源,导致其它线程都无法访问被它占用的锁,直到调用resume()。已过时,不建议使用。 |
4. 常用方法——优先级
每个线程都有一定的优先级,同优先级线程组成先进先出队列(先到先服务),使用分时调度策略。优先级高的线程采用抢占式策略,获得较多的执行机会。每个线程默认的优先级都与创建它的父线程具有相同的优先级。
构造器 | 描述 |
---|---|
MAX_PRIORITY(10)三个优先级常量之一 | 最高优先级 |
MIN _PRIORITY (1)三个优先级常量之一 | 最低优先级 |
NORM_PRIORITY (5)三个优先级常量之一 | 普通优先级,默认情况下main线程具有普通优先级。 |
public final int getPriority() | 返回线程优先级 |
public final void setPriority(int newPriority) | 改变线程的优先级,范围在[1,10]之间。 |
5. 线程的生命周期
jdk1.5 之前的5种状态:
jdk1.5 之后的6种状态:
- 将准备和运行合并为一个Runnable状态
- 将阻塞细分为:计时等待、锁阻塞、无线等待3种状态
五、解决线程的安全问题
当多个线程同时操作同一个共享数据时,就会出现线程的安全问题。
方式一:同步代码块
/**
* 1.同步监视器,俗称锁。哪个线程获得了锁,哪个线程就能执行该代码块
* 2.同步监视器可以是任何一个类的对象。但是,多个线程必须共用同一个同步监视器,且该对象是唯一的(只有一个实例对象)。
* >可以自定义一个专用于线程锁的类,然后在这里创建对象作为锁使用。
* >可以使用this充当锁,this指向当前对象。但是要注意当前类是否只创建了一个对象(保证唯一性)
* >在继承Thread的方式中不可以使用this,因为每一个线程都需要创建对象,不满足唯一性
* >在继承Thread的方式中,创建对象作为锁也需要声明为static的才可以,static Object obj = new Pbject();
* >可以使用“当前类.class”充当锁。因为“Class clz = 类.class”是一个类,仅加载一次,是全局唯一的(反射),该方式在实现Runnable中也可以使用
*
*/
synchronized(同步监视器){// 需要被同步的代码,即操作共享数据的代码
}
方式二:同步方法
/*
*用synchronized 直接修饰操作同步代码的方法
* 1.在非static的方法中,默认锁是:this。锁无法修改,因而在继承Thread方法中不适用,可以改成同步代码块方式,手动添加将当前类做为锁
* 2.在static的方法中,默认的锁是:当前类.class。即当前类本身。
*
*/
// 示例代码:在run()方法中调用show()方法
public synchronized void show(){// 操作共享数据的代码
}
相关文章:
【Java】创建多线程的四种方式
一、方式1:继承Thread类 步骤: 创建一个继承于Thread类的子类重写Thread类的run()方法 ----> 此线程执行的操作声明在方法体中创建当前Thread子类的对象通过实例对象调用start()方法,启动线程 ----> Java虚拟机会调用run()方法 注意…...
【数据结构】队列的接口实现(附图解和源码)
队列的接口实现(附图解和源码) 文章目录队列的接口实现(附图解和源码)前言一、定义结构体二、接口实现(附图解源码)1.初始化队列2.销毁队列3.队尾入队列4.判断队列是否为空5.队头出队列6.获取队列头部元素7…...
日本知名动画公司东映动画加入 The Sandbox 元宇宙
与 Minto 合作将东映动画的 IP 呈现在元宇宙。 The Sandbox 很荣幸能与东映动画合作,与 Minto 携手在 The Sandbox 元宇宙中创建基于东映动画 IP 的相关体验。 作为日本动画的先驱,东映动画制作了日本最大和世界领先的动画作品,包括《龙珠》、…...
QuickHMI Hawk R3 Crack
基于网络的 SCADA / HMI 系统 QuickHMI Hawk R3 QuickHMI是一个 100% 基于网络的SCADA/HMI 系统。 得益于HTML5、SVG和Javascript等现代网络技术,可视化可以在任何当前浏览器和设备中显示。作为浏览器的替代品,可以使用“独立查看器”和移动应用程序。 Q…...
【C语言】寻找隐藏字母游戏
编程实现一个游戏程序,会将连续三个字母中的一个隐去,由玩家填写隐去的那个字母,如屏幕上显示A ? C,则玩家需要输入B;屏幕上显示?B C,则玩家需要输入A。记录玩家完成20次游戏的时间以及正确率。…...
【C++】list 相关接口的模拟实现
list 模拟实现回顾准备构造析构函数的构造构造方法析构方法赋值运算符重载容量相关接口元素获取元素修改相关接口push 、popinserterase清空交换迭代器 **(重点)迭代器基本概念迭代器模拟实现回顾 在上一篇博客中我们大致了解了 list 相关接口的使用方法…...
快速找到外贸客户的9种方法(建议收藏)
所有外贸企业想要做好外贸出口的头等大事,就是要快速的找到优质的外贸客户和订单,没有订单的达成,所有的努力都是图劳,还有可能会陷入一种虚假的繁荣,每天都很忙,但是没有结果。今天,小编就来分…...
TCP状态转换
欢迎关注博主 Mindtechnist 或加入【Linux C/C/Python社区】一起探讨和分享Linux C/C/Python/Shell编程、机器人技术、机器学习、机器视觉、嵌入式AI相关领域的知识和技术。 TCP状态转换专栏:《Linux从小白到大神》《网络编程》 TCP状态转换示意图如下 针对上面的示…...
3500年里,印度被11个文明征服
转自:3500年里,印度被11个文明征服,如今看似统一,实际上却是缝合怪 (qq.com)今天的印度是亚洲第二大国,南亚第一大国,世界第二人口大国。如果我们将时间线拉长,纵观历史的长河,就会惊…...
Java编程问题top100---基础语法系列(一)
Java编程问题top100---基础语法系列一一、Java 操作符实质二、将InputStream转换为String使用IOUtils自己写轮子三、将数组转换为List四、如何遍历map对象使用For-Each迭代entries(方法一)使用For-Each迭代keys和values(方法二)使…...
【C#基础】C# 异常处理操作
序号系列文章6【C#基础】C# 常用语句讲解7【C#基础】C# 常用数据结构8【C#基础】C# 面向对象编程文章目录前言1,异常的概念2,处理异常3,自定义异常4,编译器异常结语前言 🌷大家好,我是writer桑,…...
系统分析师---操作系统思维导图
进程管理(5星) 进程与线程:共享:内存地址空间、代码、数据、文件等不能共享:独立的cpu运行上下文和栈指针、寄存器 信号量与PV操作:信号量,一种特殊的变量分为:信号量可以表示资源数…...
Linux | Ubuntu20.04系统使用命令从移动硬盘/U盘拷贝文件到服务器上
*确认自己移动硬盘、U盘的格式,本文为exfat格式STEP1:把移动硬盘插到Ubuntu系统的主机上查看disk默认位置#查看移动硬盘/U盘在哪个位置命令 fdisk -l #查询后出现了包含电脑系统的所有硬盘查看最后的位置,我的显示为Device, 位置为 /dev/sdb1…...
【经验总结】10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的?
【经验总结】一位近10年的嵌入式开发老手,到底是如何快速学习和使用RT-Thread的? RT-Thread绝对可以称得上国内优秀且排名靠前的操作系统,在嵌入式IoT领域一直享有盛名。近些年,物联网产业的大热,更是直接将RT-Thread这…...
一起Talk Android吧(第五百零九回:约束布局中的组功能一)
文章目录功能介绍使用方法GroupLayer对比总结各位看官们大家好,上一回中咱们说的例子是"多层布局功能",这一回中咱们说的例子是"约束布局中的组功能"。闲话休提,言归正转, 让我们一起Talk Android吧! 功能介…...
2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书
2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书2023安徽省“中银杯”职业技能大赛“网络安全” 项目比赛任务书A模块基础设施设置/安全加固(200分)A-1:登录安全加固(Windows, Linux)A-2:Ngi…...
观测云产品更新|新增用户访问监测自动化追踪;新增 CDN 质量分析;新增自定义查看器导航菜单等
观测云更新 用户访问监测优化 新增用户访问监测自动化追踪 用户访问监测新增自动化追踪,通过“浏览器插件”的实现方式,使用浏览器记录用户访问行为,创建无代码的端到端测试。更多详情可参考文档【 自动化追踪 】https://docs.guance.com/…...
大数据技术生态全景一览
大数据技术生态全景一览大数据平台ETL数据接入大数据平台海量数据存储大数据平台通用计算大数据平台各场景的分析运算分布式协调服务任务流调度引擎大数据平台ETL数据接入 大数据有很多的产品,琳琅满目。从架构图上就能看出产品很多。这些产品它们各自的功能是什么…...
CI/CD | 深入研究Jenkins后,我挖掘出了找到了摆脱低效率低下的方法
在本系列的第一篇文章中,您已经了解了一些关于如何管理Jenkins的内容,主要是为无序的人带来秩序。在这篇文章中,我将更深入地探讨我效率低下的问题,提出我们工作流中一些安全性、治理和合规性的挑战。这不仅仅是你在网站上或展览横…...
刷LeetCode
文章目录滑动窗口算法1 涉及知识点 :unordered_set 容器2 参数详情3 例题滑动窗口算法 滑动的窗口,每次记录下窗口的状态,再找出符合条件的窗口使用滑动窗口减少时间复杂度 1 涉及知识点 :unordered_set 容器 说明:…...
Spring 大白话系列:工厂
Spring 大白话系列:工厂 “工厂模式,大家都很熟悉了。说到底,就是解除创建对象和使用对象之间的耦合。这东西没啥啊。” 教室里,老师傅听到小明在嘀嘀咕咕的。老师走过去问: “有什么问题呢小明同学?” 小…...
喜讯!华秋电子荣获第六届“蓝点奖”十佳分销商奖
2 月 25 日,由深圳市电子商会主办的2023 中国电子信息产业创新发展交流大会暨第六届蓝点奖颁奖盛典在深圳隆重举行。 图:华秋商城渠道总监杨阳(右三) 深圳市电子商会连续六年举办“蓝点奖”评选活动,旨在表彰对电子信…...
Linux概述
1:Linux概述1.1:操作系统常见操作系统有:Windows、MacOS、Linux。名称描述Windows微软公司研发的收费操作系统。分为两类:用户操作系统、Server操作系统。用户操作系统:win 95、win 98、win NT、win Me、win xp、vista…...
中级嵌入式系统设计师2015下半年上午试题及答案解析
中级嵌入式系统设计师2015下半年上午试题 单项选择题 1、CPU是在______结束时响应DMA请求的。 A.一条指令执行 B.一段程序 C.一个时钟周期 D.一个总线周期 2、虚拟存储体系由______两级存储器构成。 A.主存-辅存 B.寄存器-Cache C.寄存器-主存...
华为OD机试模拟题 用 C++ 实现 - 删除指定目录(2023.Q1)
最近更新的博客 【华为OD机试模拟题】用 C++ 实现 - 最多获得的短信条数(2023.Q1)) 文章目录 最近更新的博客使用说明删除指定目录题目输入输出示例一输入输出说明Code使用说明 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为…...
【正点原子FPGA连载】第二十章AXI4接口之DDR读写实验 摘自【正点原子】DFZU2EG_4EV MPSoC之嵌入式Vitis开发指南
1)实验平台:正点原子MPSoC开发板 2)平台购买地址:https://detail.tmall.com/item.htm?id692450874670 3)全套实验源码手册视频下载地址: http://www.openedv.com/thread-340252-1-1.html 第二十章AXI4接口…...
超出认知的数据压缩 用1-bit数据来表示32-bit的梯度 语音识别分布式机器学习 梯度压缩 论文精读
说明 介绍1−bit1-bit1−bit论文内容。 原文链接:1-bit stochastic gradient descent and its application to data-parallel distributed training of speech DNNs | Semantic Scholar ABS 实验证明在分布式机器学习的过程中能够通过将同步所传递的梯度进行量化…...
深度剖析指针(上)——“C”
各位CSDN的uu们你们好呀,今天,小雅兰的内容是指针噢,在学习C语言的过程中,指针算是一个比较重要的内容,当然,难度也是比较大的,那么现在就让小雅兰来带大家进入指针的世界吧 字符指针 数组指针…...
学习 Python 之 Pygame 开发魂斗罗(六)
学习 Python 之 Pygame 开发魂斗罗(六)继续编写魂斗罗1. 创建碰撞类2. 给地图添加碰撞体3. 让人物可以掉下去4. 实现人物向下跳跃5. 完整的代码继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗(五)中,我…...
LeetCode题解:1238. 循环码排列,归纳法,详细注释
原题链接: https://leetcode.cn/problems/circular-permutation-in-binary-representation/ 前置条件: 在解题之前,请先一定要阅读89.格雷编码的题解格雷编码可以满足题目的条件“p[i] 和 p[i1] 的二进制表示形式只有一位不同”,…...
宁波专业做网站公司/优化落实新十条措施
下載转载于:https://www.cnblogs.com/wang123/archive/2008/02/21/1076370.html...
郑州网站建设贝斯特/百度近日收录查询
1. MySQL WorkbenchMySQL Workbench 为数据库管理员、程序开发者和系统规划师提供可视化的Sql开发、数据库建模、以及数据库管理功能。2.MySQL Workbench 的下载和安装(1)安装最新MySql时,有是否安装MySql Workbench的选项,可选择安装。(2)可以独立安装M…...
wordpress教程 下载地址/希爱力吃一颗能干多久
第一种:在本地已创建文件目录,连接方式1,用git bash 进入到文件目录下$ git init #通过命令把目录变成Git可以管理的仓库(初始化一个git仓库)$ ls -a2, 将工作区文件-----------》添加…...
哪个网站做效果图好/seo专员是什么意思
这篇文章我们主要从整体上了解一下计算机程序是如何运行的。在此过程中,我们将会引出操作系统中一些很重要的概念,并在后续的文章中对这些概念将强化和深入理解。首先从计算机的硬件开始谈起。在这里我们只考虑和程序运行直接相关的硬件。其基本的硬件如…...
有什么做网站的公司/全国免费发布信息平台
闭包是什么,作用? 函数可以访问其外部定义的变量,但是函数内部对该变量进行的修改,在函数外是不可见的,即对函数作用域外变量不会产生影响。 比如一个人在美国,办了美国国籍,然后回到中国&…...
网络营销推广的重要性/营销网站seo推广
推荐书籍 等我把《笨办法学Python》学完后,就重返Python3,好好学习一下这本书。...