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,一经查实,立即删除!

相关文章

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

引言&#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;释…

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

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

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六种编程语言的代码生成…

《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…

YOLOv7-tiny,通过pycocotools包得到预测大中小尺寸目标的指标值

文章目录 参考链接步骤认识正确的instances_val2017.json文件格式 代码&#xff08;mogui_tococo.py&#xff0c;用于我自己的数据集&#xff09; 参考链接 需要先在环境中安装pycocotools pip install pycocotools魔鬼面具的代码&#xff1a;objectdetection-tricks/tricks_…

第 379 场 LeetCode 周赛题解

A 对角线最长的矩形的面积 模拟 class Solution { public:int areaOfMaxDiagonal(vector<vector<int>> &dimensions) {int res 0, len2 0;for (auto &x: dimensions)if (x[0] * x[0] x[1] * x[1] > len2 || x[0] * x[0] x[1] * x[1] len2 &&am…

SAP 如何快速查询成本的异常

每当月末CO月结的时候&#xff0c;生产企业或多或少会遇到标准成本与实际成本差异偏大的情况&#xff0c;我们如何快速查看产成品的成本异常&#xff0c;一般来说二者偏差5%是正常的&#xff0c;如果偏差20%&#xff0c;就要重点关注。我们通过0062报表来查看 进入“屏幕选择”…

进销存+小程序商城:实现批发零售企业的互联网转型与管理升级

在当今互联网高速发展的时代&#xff0c;越来越多的批发零售企业开始开始考虑转型。在这个行业中&#xff0c;企业要想取得更好的发展&#xff0c;就要积极地拥抱互联网。专属的订货商城小程序是企业转型的第一步。通过将进销存与订货商城一体化&#xff0c;企业可以更好地满足…

argparse库

引言 argparse-------python用于解析命令行参数的标准模块 快速上手 import argparse parser argparse.ArgumentParser() 创建一个命令行解析器对象 parser.add_argument() 向解析器…

APP流量变现——4项关键指标决定了APP混合变现的收入

APP流量变现的方式有很多种&#xff0c;主要的可以分为IAA&#xff08;广告&#xff09;收入、IAP&#xff08;用户应用内付费&#xff09;收入、订阅收入、单次买断收入。这里主要围绕当前流行的混合变现模式&#xff0c;即广告收入&#xff08;IAA&#xff09;应用内付费&…

外汇天眼:塞浦路斯证券交易委员会(CySEC)确认了四家投资公司退出投资者赔偿基金(ICF)会员资格

塞浦路斯证券交易委员会&#xff08;CySEC&#xff09;今天确认了四家投资公司已被取消其在投资者赔偿基金&#xff08;ICF&#xff09;的会员资格。 以下公司不再是ICF的会员&#xff1a; 1.Stone Edge Capital Ltd&#xff08;LEI 213800PZFB9VV8FNWB30&#xff09;&#xf…

yum来安装php727

yum 安装php727,一键安装&#xff0c;都是安装在系统的默认位置&#xff0c;方便快捷 先确定linux平台中centos的版本信息&#xff0c;一下内容针对el7 查看linux版本 &#xff1a; cat /etc/redhat-release 查看内核版本命令&#xff1a; cat /proc/version (0)如果有安装好…

3万字数据结构与算法学习笔记+知识点总结

文章目录 数据结构与算法排序排序算法常见排序算法复杂度冒泡排序&#xff08;Bubble Sort&#xff09;选择排序&#xff08;Selection Sort&#xff09;插入排序&#xff08;Insertion Sort&#xff09;希尔排序&#xff08;Shell Sort&#xff09;堆排序&#xff08;Heap Sor…