Java中的多线程

进程和线程的概念

进程是应用程序的执行实例有独立的内存空间和系统资源。

线程是进程中执行运算的最小单位,可完成一个独立的顺序控制流程
一。一个进程可以包含多个线程,每个线程都独立执行特定的任务,
是CPU调度和分派的基本单位。

多线程的概念:

  • 如果在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为“多线程”
  • 多个线程交替占用CPU资源,而非真正的并行执行

多线程的好处:

  • 充分利用CPU的资源
  • 简化编程模型
  • 带来良好的用户体验

主线程:
Thread类

Java提供了java.lang.Thread类支持多线程编程

主线程

  • main()方法即为主线程入口
  • 产生其他子线程的线程
  • 必须最后完成执行,因为它执行各种关闭动作
public static void main(String args[]) {Thread t= Thread.currentThread(); System.out.println("当前线程是: "+t.getName()); t.setName("MyJavaThread"); System.out.println("当前线程名是: "+t.getName()); }

线程的创建和启动

在Java中,可以通过继承Thread类或实现Runnable接口来创建线程。
在这里插入图片描述

  1. 继承Thread类:
    I. 定义MyThread类继承Thread类
    ||. 重写run()方法,编写线程执行体
    |||. 创建线程对象,调用start()方法启动线程
public class MyThread extends Thread {public void run() {// 线程执行的代码}
}// 创建并启动线程
MyThread thread = new MyThread();
thread.start();

补充:

多线程里的多个线程交替执行,而不是真正的“并行”。
线程每次执行时长由分配的CPU时间片长度决定。

  1. 实现Runnable接口:
    |.定义MyRunnable类实现Runnable接口
    ||.实现run()方法,编写线程执行体
    |||.创建线程对象,调用start()方法启动线程
public class MyRunnable implements Runnable {public void run() {// 线程执行的代码}
}
// 创建并启动线程
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();

调用线程的run()和start()方法的区别如下:

run()方法:直接调用线程对象的run()方法会在当前线程中执行该方法的代码,就像普通的方法调用一样。并不会创建新的线程,而是在当前线程中按顺序执行。所以只有主线程main一条执行路径。

start()方法:调用线程对象的start()方法会创建一个新的线程,并在新的线程中执行run()方法的代码。start()方法会启动线程的执行,然后立即返回,不会阻塞当前线程。所以具体执行过程有多条执行路径,主线程和子线程并行交替执行

总结来说,直接调用run()方法只会在当前线程中执行方法的代码,不会创建新的线程。而调用start()方法会创建新的线程,并在新线程中执行方法的代码。通常情况下,我们应该使用start()方法来启动线程,以实现多线程并发执行的效果。

比较两种创建线程的方式

继承Thread类:

  • 编写简单,可直接操作线程
  • 适用于单继承

实现Runnable接口

  • 避免单继承局限性
  • 便于共享资源

线程的状态

线程在生命周期中有多个状态:
线程共包括以下 5 种状态:

下面是使用Markdown语法写的嵌套列表:

线程共包括以下 5 种状态:

  1. 新建状态(New): 线程对象被创建后,就进入了新建状态。例如,Thread thread = new Thread()

  2. 就绪状态(Runnable): 也被称为“可执行状态”。线程对象被创建后,其它线程调用了该对象的start()方法,从而来启动该线程。例如,thread.start()。处于就绪状态的线程,随时可能被CPU调度执行。

  3. 运行状态(Running): 线程获取CPU权限进行执行。需要注意的是,线程只能从就绪状态进入到运行状态。

  4. 阻塞状态(Blocked): 阻塞状态是线程因为某种原因放弃CPU使用权,暂时停止运行。直到线程进入就绪状态,才有机会转到运行状态。阻塞的情况分三种:

    • 等待阻塞 – 通过调用线程的wait()方法,让线程等待某工作的完成。
    • 同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态。
    • 其他阻塞 – 通过调用线程的sleep()join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
  5. 死亡状态(Dead): 线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

线程调度的常用方法

线程调度指操作系统或Java虚拟机按照特定机制为多个线程分配CPU的使用权。Java提供了一些常用的线程调度方法:

方法
void setPriority(int newPriority)更改线程的优先级
static void sleep(long millis)在指定的毫秒数内让当前正在执行的线程休眠
void join()等待该线程终止
static void yield()暂停当前正在执行的线程对象,并执行其他线程
void interrupt()中断线程
boolean isAlive()测试线程是否处于活动状态
  1. 线程优先级
    • 线程优先级由1~10表示,1最低,默认优先级为5
    • 优先级高的线程获得CPU资源的概率较大
public static void main(String[] args) {Thread t1 = new Thread(new MyThread(),"线程A");Thread t2 = new Thread(new MyThread(),"线程B");t1.setPriority(Thread.MAX_PRIORITY);t2.setPriority(Thread.MIN_PRIORITY);//省略代码……}}
  1. static void sleep(long millis):使当前线程暂停执行一段时间。
    • millis为休眠时长,以毫秒为单位
    • 调用sleep()方法需处理InterruptedException异常
try {Thread.sleep(1000); // 暂停1秒
} catch (InterruptedException e) {e.printStackTrace();
}
  • yield():暂停当前正在执行的线程,让出CPU资源给其他线程。
Thread.yield();
  1. join():等待其他线程执行完毕再继续执行。
  • public final void join()

  • public final void join(long mills)

  • public final void join(long mills,int nanos)

    • millis:以毫秒为单位的等待时长
    • nanos:要等待的附加纳秒时长
    • 需处理InterruptedException异常
Thread thread1 = new Thread();
Thread thread2 = new Thread();thread1.start();
thread2.start();try {thread1.join(); // 等待thread1执行完毕thread2.join(); // 等待thread2执行完毕
} catch (InterruptedException e) {e.printStackTrace();
}

5.public static void yield()线程的礼让

  • 暂停当前线程,允许其他具有相同优先级的线程获得运行机会
  • 该线程处于就绪状态,不转为阻塞状态

只是提供一种可能,但是不能保证一定会实现礼让

public class MyThread implements Runnable{public void run(){for(int i=0;i<5;i++){System.out.println(Thread.currentThread().getName()+"正在运行:"+i);if(i==3){System.out.print("线程礼让:");Thread.yield();	} } }}

线程的同步

多个线程访问共享资源时可能会出现数据不一致的问题,需要使用同步机制来保证线程安全。

  1. synchronized关键字:可以修饰方法或代码块,确保同一时间只有一个线程执行。
    方法:
    在这里插入图片描述
    代码块:
    在这里插入图片描述
public synchronized void synchronizedMethod() {// 同步的方法
}public void someMethod() {synchronized (this) {// 同步的代码块}
}
  1. Lock对象:使用Lock接口的实现类来实现同步。
Lock lock = new ReentrantLock();lock.lock(); // 获取锁try {// 同步的代码块
} finally {lock.unlock(); // 释放锁
}

多个并发线程访问同一资源的同步代码块时

  1. 同一时刻只能有一个线程进入synchronized(this)同步代码块
  2. 当一个线程访问一个synchronized(this)同步代码块时,其他synchronized(this)同步代码块同样被锁定
  3. 当一个线程访问一个synchronized(this)同步代码块时,其他线程可以访问该资源的非synchronized(this)同步代码

Java中常见的线程安全类型及其比较:

  1. ArrayList vs. Vector:

    • ArrayList是非线程安全的类型,适用于单线程环境下的操作。
    • Vector是线程安全的类型,适用于多线程环境下的操作。Vector的方法使用了synchronized关键字进行同步,保证了线程安全。
      在这里插入图片描述
  2. Hashtable vs. HashMap:

    • Hashtable是线程安全的类型,适用于多线程环境下的操作。Hashtable的方法使用了synchronized关键字进行同步,保证了线程安全。
    • HashMap是非线程安全的类型,适用于单线程环境下的操作。HashMap的方法没有进行同步,不保证线程安全。

在这里插入图片描述

  1. StringBuffer vs. StringBuilder:
    • StringBuffer是线程安全的类型,适用于多线程环境下的操作。StringBuffer的方法使用了synchronized关键字进行同步,保证了线程安全。
    • StringBuilder是非线程安全的类型,适用于单线程环境下的操作。StringBuilder的方法没有进行同步,不保证线程安全。

需要注意的是,虽然线程安全的类型在多线程环境下可以保证数据的一致性和正确性,但在性能上可能会有一定的开销。非线程安全的类型在多线程环境下需要额外的同步措施来保证数据的安全性。因此,在选择使用哪种类型时,需要根据具体的需求和场景进行权衡和选择。
在这里插入图片描述

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

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

相关文章

JAVA数学区间计算,支持开闭区间、百分比、-∞、+∞

import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import java.math.BigDecimal; import java.math.RoundingMode;/*** 判断数值是否在数学区间范围内** author AnNong* date 2023-04-07*/ public class IntervalUtil {public static ScriptEngine…

前端生成pdf之html2canvas+jsPDF,以及解决图片不显示bug

前端如何生成pdf 开发背景&#xff1a; 需要给页面中相应的内容生成pdf&#xff0c;查找文档后发现要用到两个插件。html2canvas 以及 jsPDF html2canvas 给dom结构转化为canvas&#xff0c;然后生成各种类型图片jsPDF 把canvas 生成的图片url 转化为pdf // 插入图片 pdf.addI…

3.【CPP入门】(深浅拷贝||运算符重载||赋值运算符重载)

一.浅拷贝和深拷贝 1.引入 从上篇博客拷贝构造我们知道拷贝构造要传引用而不能传值&#xff0c;否则会发生无穷递归的情况。 1.若未显示定义拷贝构造函数&#xff0c;系统会生成默认的拷贝构造函数。默认的拷贝构造按内存序完成拷贝&#xff0c;我们称之为浅拷贝&#xff08;…

python中迭代器的应用

迭代器&#xff08;Iterator&#xff09;在Python中是一种用于迭代访问元素的对象&#xff0c;它提供了一种统一的访问集合元素的方式。迭代器通常与可迭代对象&#xff08;Iterable&#xff09;一起使用&#xff0c;如列表、元组、字典等。以下是迭代器在Python中的应用场景&a…

开机自启动app

问&#xff1a;在android系统的tv上&#xff0c;用遥控器可以控制光标位置&#xff0c;这是不是有一些监听事件实现的&#xff0c;具体原理是什么 答&#xff1a; 在 Android TV 上&#xff0c;使用遥控器来控制光标位置的功能是通过处理按键事件和焦点控制来实现的。 Andro…

「许战海矩阵战略洞察」从“老干妈”看全国辣椒酱企业的发展战略

引言&#xff1a;老干妈作为辣椒酱行业的领导品牌&#xff0c;虽然市场份额大&#xff0c;但增长缓慢。本文分析了老干妈的成功秘诀和增长挑战&#xff0c;提出了建立组合信任、强化渠道管控和打造第二招牌产品的战略建议。同时&#xff0c;给我国辣椒酱企业提供了佐餐酱和烹饪…

Android Studio安卓读写NFC Ntag标签源码

本示例使用的发卡器&#xff1a; https://item.taobao.com/item.htm?spma1z10.5-c-s.w4002-21818769070.11.3513789erHXVGx&id615391857885 <?xml version"1.0" encoding"utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout x…

边缘计算的舞台,挑战与机遇相伴

目录 前言 边缘计算保卫战&#xff1a;数据宝藏的隐藏与探索 稳如磐石&#xff1a;保障你的边缘计算宝藏安稳运行&#xff01; 打破时间的桎梏&#xff1a;为边缘计算注入超快速度与实时表演 边缘计算&#xff1a;应对多样性和异构性的酷炫策略大揭秘 边缘计算&#xff1a;释…

中间件:构建现代软件架构的桥梁

一、前言 在当今快速发展的科技领域中&#xff0c;软件系统的复杂性不断增加。为了应对这一挑战&#xff0c;中间件应运而生&#xff0c;成为连接和协调不同软件组件的不可或缺的桥梁。本文将深入探讨中间件的基本概念、作用以及一些常见的中间件类型。 二、中间件的定义 中间…

C#实现Excel合并单元格数据导入数据集

目录 功能需求 Excel与DataSet的映射关系 范例运行环境 Excel DCOM 配置 设计实现 组件库引入 ​方法设计 返回值 参数设计 打开数据源并计算Sheets 拆分合并的单元格 创建DataTable 将单元格数据写入DataTable 总结 功能需求 将Excel里的worksheet表格导入到Da…

02.阿里Java开发手册——日期时间

【强制】日期格式化时&#xff0c;传入 pattern 中表示年份统一使用小写的 y。 说明&#xff1a;日期格式化时&#xff0c;yyyy 表示当天所在的年&#xff0c;而大写的 YYYY 代表是 week in which year&#xff08;JDK7 之后引入的概念&#xff09;&#xff0c;意思是当天所在的…

2023年全国职业院校技能大赛软件测试赛题—单元测试卷④

任务二 单元测试 一、任务要求 题目1&#xff1a;根据下列流程图编写程序实现相应分析处理并显示结果。返回结果“ax&#xff1a;”&#xff08;x为2、3或4&#xff09;&#xff1b;其中变量x、y均须为整型。编写程序代码&#xff0c;使用JUnit框架编写测试类对编写的程序代码…

通义千问AI挑战赛赛后反思

个人理解&#xff1a; 初赛阶段主要聚焦在如何通过 SFT 提升基础模型的代码能力&#xff0c;需要选手基于最新开源的 Qwen 1.8 模型作为基础模型&#xff0c;上分的关键主要通过收集高质量的代码数据提升模型的在Python, JavaScript, Java, Go, C, Rust六种编程语言的代码生成…

Echarts封装动态加载组件,并且添加循环效果

基于 Echarts 框架的组件&#xff0c;用于实现数据滚动效果。在该组件中&#xff0c;我们首先引入了 Echarts 库&#xff0c;并定义了组件的名称和所需的 props 属性。在 mounted 钩子函数中&#xff0c;我们调用 initChart 方法来初始化图表&#xff0c;并使用 setInterval 定…

《SPSS统计学基础与实证研究应用精解》视频讲解:SPSS依托统计学处理数据的应用场景

《SPSS统计学基础与实证研究应用精解》1.4 视频讲解 视频为《SPSS统计学基础与实证研究应用精解》张甜 杨维忠著 清华大学出版社 一书的随书赠送视频讲解1.4节内容。本书已正式出版上市&#xff0c;当当、京东、淘宝等平台热销中&#xff0c;搜索书名即可。本书旨在手把手教会使…

肝了半个月的学习路线终于上线了,升职加薪,轻松拿捏!

大家好&#xff0c;我是冰河~~ 最近有不少小伙伴问我出去面试找一份好工作要学习哪些知识和技术&#xff0c;有没有什么好的学习路线&#xff0c;这不&#xff0c;我连夜肝了这份Java完整高清学习路线。 学习路线 完整路线 这份Java完整高清学习路线的总体路线图如下所示。…

微信小程序开发学习笔记《7》全局配置以及小程序窗口

微信小程序开发学习笔记《7》全局配置以及小程序窗口 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。全局配置官方文档 一、全局配置文件及常用的配置项 小程序根目录下的app.json 文件是小程序的全局配置文件。 常用的配置项如…

Redis的实现三:c语言实现平衡二叉树,通过平衡二叉树实现排序集

概况&#xff1a;Redis中的排序集数据结构是相当复杂的独特而有用的东西。它不仅提供了顺序排序数据的能力&#xff0c;而且具有按排名查询有序数据的独特特性。 Redis中的排序集 &#xff08;Sorted Set&#xff09;是一种特殊的数据结构&#xff0c;它结合了集合&#xff0…

C //练习 4-14 定义宏swap(t, x, y)以交换t类型的两个参数。(使用程序块结构会对你有所帮助。)

C程序设计语言 &#xff08;第二版&#xff09; 练习 4-14 练习 4-14 定义宏swap(t, x, y)以交换t类型的两个参数。&#xff08;使用程序块结构会对你有所帮助。&#xff09; 注意&#xff1a;代码在win32控制台运行&#xff0c;在不同的IDE环境下&#xff0c;有部分可能需要…