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.rhkb.cn/news/236105.html

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

相关文章

轴承滚珠故障的理论推导与计算(修订中...)

1.缘起 轴承故障故障位置在高频&#xff0c;如果不即时处理&#xff0c;恶化后&#xff0c;滚珠会有单颗故障迅速恶化到多颗&#xff0c;如果此时电机承载较大负载&#xff0c;轴承的恶化&#xff0c;会牵连到相关的动力轴。是一个不可不进行监测的项目。 2.频谱特征 轴承的…

【AWS】使用亚马逊云服务器创建EC2实例

目录 前言为什么选择 Amazon EC2 云服务器搭建 Amazon EC2 云服务器注册亚马逊账号登录控制台服务器配置免费套餐预览使用 Amazon EC2 云服务器打开服务器管理界面设置服务器区域填写实例名称选择服务器系统镜像选择实例类型创建密钥对网络设置配置存储启动实例查看实例 总结 前…

Window平台安装MongoDB

在部署前需要在官网先确定系统对应的Mongo DB版本。 本机电脑为Window10&#xff0c;所以这里以MongoDB 6.0版本。 1 在官网下载安装包 2 安装MongoDB MongoDB Compass 是一个图形界面管理工具&#xff0c;如果勾选了安装会花费长一点时间&#xff0c;可以取消掉勾选&#xff…

2024最新适用于 Windows 、Mac 的最佳屏幕录制软件

屏幕录制软件可以帮助我们录制 PC 和MacBook的实时屏幕视频。如果您想为 优酷录制视频&#xff0c;或者您正在为您的公司制作基于视频的项目&#xff0c;并且需要捕获屏幕的实时视频录制&#xff0c;那么我们在此列出了 一 款适合您的 Windows 、Mac的 2024 年最佳屏幕录制软件…

《NLP入门到精通》栏目导读

一、说明 栏目《NLP入门到精通》本着从简到难得台阶式学习过度。将自然语言处理得知识贯穿过来。本栏目得前导栏目是《深度学习》、《pytorch实践》&#xff0c;因此&#xff0c;读者需要一定得深度学习基础&#xff0c;才能过度到此栏目内容。 二、博客建设理念 本博客基地&am…

Transformer详解【学习笔记】

文章目录 1、Transformer绪论2、Encoders和Decoder2.1 Encoders2.1.1 输入部分2.1.2 多头注意力机制2.1.3 残差2.1.4 LayNorm&#xff08;Layer Normalization&#xff09;2.1.5 前馈神经网路 2.2 Decoder2.2.1 多头注意力机制2.2.2 交互层 1、Transformer绪论 Transformer在做…

RabbitMQ(十)队列的声明方式

目录 1.编程式声明补充&#xff1a;RabbitTemplate 和 AmqpAdmin 的区别 2.声明式声明补充&#xff1a;new Queue() 和 QueueBuilder.durable(queueName).build() 的区别 背景&#xff1a; 在学习 RabbitMQ 的使用时&#xff0c; 经常会遇到不同的队列声明方式&#xff0c;有的…

Redis管道操作

文章目录 1. 问题提出2. 解决方案3. 案例演示4. 总结 1. 问题提出 如何优化频繁命令往返造成的性能瓶颈&#xff1f; Redis是一种基于C/S一级请求响应协议的TCP服务&#xff0c;一个请求会遵循一下步骤&#xff1a; 客户端向服务端发送命令分四步&#xff08;发送命令-> …

个人网站制作 Part 1 | Web开发项目

文章目录 &#x1f469;‍&#x1f4bb; 基础Web开发练手项目系列&#xff1a;个人网站制作&#x1f680; 项目概述&#x1f527; 开发工具和环境配置&#x1f6e0; 项目实现步骤步骤 1: 创建HTML文件步骤 2: 添加CSS样式步骤 3: 链接CSS文件步骤 4: 添加JavaScript交互 &#…

Unity中向量的点乘、叉乘区别和作用以及经典案例

文章目录 点乘&#xff08;Dot Product&#xff09;叉乘&#xff08;Cross Product&#xff09;向量归一化&#xff08;Normalize&#xff09;其他作用 unity开发中我们要计算角度&#xff0c;判断位置&#xff0c;常用点乘、叉乘、归一化等等&#xff0c;我们看看他们的使用案…

tiktok_浅谈hook ios之发包x-ss-stub

frida-trace ios手机一部&#xff0c;需要越狱的电脑一台idacrackerXI 目标app&#xff1a; ipa 包&#xff0c;点击前往 密码&#xff1a;8urs 协议分析起始从抓包开始&#xff0c;个人习惯 一般安卓逆向可以直接搜关键词&#xff0c;但是ios 都在 Mach-O binary (reverse…

微服务-Gateway

案例搭建 官网地址 父Pom <com.alibaba.cloud.version>2.2.8.RELEASE</com.alibaba.cloud.version> <com.cloud.version>Hoxton.SR12</com.cloud.version> <com.dubbo.version>2.2.7.RELEASE</com.dubbo.version> <dependencyManagem…

SQL-DML增删改

&#x1f389;欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦)o *☆哈喽~我是小小恶斯法克&#x1f379; ✨博客主页&#xff1a;小小恶斯法克的博客 &#x1f388;该系列文章专栏&#xff1a;重拾MySQL &#x1f379;文章作者技术和水平很有限&#xff0c;如果文中出现错误&am…

Zynq 电源

ZYNQ芯片的电源分PS系统部分和PL逻辑部分&#xff0c;两部分的电源分别是独立工作。PS系统部分的电源和PL逻辑部分的电源都有上电顺序&#xff0c;不正常的上电顺序可能会导致ARM系统和FPGA系统无法正常工作。 PS部分的电源有VCCPINT、VCCPAUX、VCCPLL和PS VCCO。 VCCPINT为PS内…

thinkphp美容SPA管理系统源码带文字安装教程

thinkphp美容SPA管理系统源码带文字安装教程 运行环境 服务器宝塔面板 PHP 7.0 Mysql 5.5及以上版本 Linux Centos7以上 基于thinkphp3.23B-JUI1.2开发&#xff0c;权限运用了Auth类认证&#xff0c;权限可以细分到每个功能&#xff0c; 增删改查功能一应俱全&#xff0c;整合了…

低维度向量的 Householder 反射变换 matlab 图示

1, 算法原理 设th 是一个弧度值&#xff0c; 令 Q | cos(th) sin(th) | | sin(th) -cos(th) | S span{ | cos(th/2.0) | } | sin(th/2.0) | x (x1, x2) 是一个平面上的二维向量 计算 y Qx Qx 则&#xff0c;y 是 x 通过有 S 定…

函数——自制函数(c++)

今天进入自制函数。 自制函数&#xff0c;需要自己定义其功能。比如&#xff0c;设置一个没有参数没有返回值的积木&#xff0c;叫“aaa”。那么&#xff0c;如果想要运行“aaa”&#xff0c;就需要以下代码&#xff1a; void aaa(); 告诉系统有“aaa”…

Java快速排序希尔排序归并排序

快速排序算法 快速排序的原理&#xff1a;选择一个关键值作为基准值。比基准值小的都在左边序列&#xff08;一般是无序的&#xff09;&#xff0c;比基准值大的都在右边&#xff08;一般是无序的&#xff09;。一般选择序列的第一个元素。 一次循环&#xff1a;从后往前比较&…

基于Python实现身份证信息识别

目录 前言身份证信息识别的背景与意义自动识别身份证的需求 实现环境与工具准备Python编程语言OpenCV图像处理库Tesseract OCR引擎 身份证信息识别算法原理图像预处理步骤(图像裁剪、灰度化 、二值化、去噪)信息提取与解析 Python代码实现通过OCR提取身份证号码代码解析身份证信…

【QML COOK】- 008-自定义属性

前面介绍了用C定义QML类型&#xff0c;通常在使用Qt Quick开发项目时&#xff0c;C定义后端数据类型&#xff0c;前端则完全使用QML实现。而QML类型或Qt Quick中的类型时不免需要为对象增加一些属性&#xff0c;本篇就来介绍如何自定义属性。 1. 创建项目&#xff0c;并编辑Ma…