当前位置: 首页 > news >正文

java中多线程的一些常见操作

Java 中的多线程是通过并发编程来提高应用程序的效率和响应速度。Java 提供了多个机制和类来支持多线程编程,包括继承 Thread 类、实现 Runnable 接口、使用线程池等。以下是 Java 中一些常见的多线程操作和应用场景。

1. 创建线程

1.1 通过继承 Thread 类创建线程

继承 Thread 类并重写 run 方法是创建线程的一种方式。run 方法包含线程的执行体。

public class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread is running: " + Thread.currentThread().getName());}public static void main(String[] args) {MyThread thread = new MyThread();thread.start();  // 启动线程}
}
  • start() 方法会启动线程并调用 run() 方法。
  • run() 方法不能直接调用,必须通过 start() 启动线程。
1.2 通过实现 Runnable 接口创建线程

Runnable 接口适合当你不想继承 Thread 类时使用。你只需要实现 run 方法,然后将其传递给 Thread 对象。

public class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Thread is running: " + Thread.currentThread().getName());}public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start();  // 启动线程}
}

2. 线程的生命周期

线程有几个常见的生命周期状态:

  • 新建(New):线程对象被创建,但未调用 start() 方法。
  • 可运行(Runnable):线程被启动,处于可运行状态,但可能被操作系统调度暂停。
  • 阻塞(Blocked):线程正在等待某个资源。
  • 等待(Waiting):线程正在等待其他线程执行某些操作。
  • 终止(Terminated):线程执行完毕,生命周期结束。

3. 线程的同步

当多个线程访问共享资源时,为了避免数据不一致的问题,通常需要使用同步机制。

3.1 使用 synchronized 关键字

synchronized 关键字用于在方法或代码块上加锁,确保在同一时间内只有一个线程能够执行被同步的代码块。

示例:同步方法
public class Counter {private int count = 0;// 使用 synchronized 修饰方法,保证线程安全public synchronized void increment() {count++;}public int getCount() {return count;}public static void main(String[] args) {Counter counter = new Counter();// 创建两个线程同时访问共享资源Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});t1.start();t2.start();try {t1.join();  // 等待线程 t1 执行完毕t2.join();  // 等待线程 t2 执行完毕} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Final count: " + counter.getCount());  // 输出: Final count: 2000}
}

在上面的例子中,increment 方法被 synchronized 修饰,这意味着同一时刻只有一个线程能够访问这个方法。

3.2 使用同步代码块

你也可以使用同步代码块来锁定指定的代码区域,从而减少锁的范围,提高效率。

public class Counter {private int count = 0;public void increment() {synchronized (this) {  // 锁定当前对象count++;}}public int getCount() {return count;}public static void main(String[] args) {Counter counter = new Counter();Thread t1 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 1000; i++) {counter.increment();}});t1.start();t2.start();try {t1.join();  // 等待线程 t1 执行完毕t2.join();  // 等待线程 t2 执行完毕} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Final count: " + counter.getCount());  // 输出: Final count: 2000}
}

在上面的代码中,increment 方法内的同步代码块确保了每次只有一个线程能够进入该代码块,防止了竞态条件的出现。

4. 线程间通信

线程间通信是在多个线程之间交换信息的机制。Java 提供了 wait()notify()notifyAll() 方法来实现线程间的通信。

4.1 使用 wait()notify() 进行线程通信
  • wait():使当前线程进入等待状态,并释放锁,直到被其他线程通知。
  • notify():通知一个正在等待的线程,使其从等待状态中醒来,继续执行。
  • notifyAll():通知所有正在等待的线程,所有线程都会尝试重新获取锁。
示例:生产者-消费者问题
class Storage {private int product = 0;private final int capacity = 10;// 生产者生产产品public synchronized void produce() throws InterruptedException {while (product >= capacity) {wait();  // 如果库存已满,生产者等待}product++;System.out.println("Produced, product count: " + product);notifyAll();  // 通知消费者线程}// 消费者消费产品public synchronized void consume() throws InterruptedException {while (product <= 0) {wait();  // 如果库存为空,消费者等待}product--;System.out.println("Consumed, product count: " + product);notifyAll();  // 通知生产者线程}
}public class ProducerConsumer {public static void main(String[] args) {Storage storage = new Storage();// 生产者线程Thread producer = new Thread(() -> {try {for (int i = 0; i < 20; i++) {storage.produce();Thread.sleep(100);  // 模拟生产时间}} catch (InterruptedException e) {e.printStackTrace();}});// 消费者线程Thread consumer = new Thread(() -> {try {for (int i = 0; i < 20; i++) {storage.consume();Thread.sleep(150);  // 模拟消费时间}} catch (InterruptedException e) {e.printStackTrace();}});producer.start();consumer.start();}
}

在这个例子中,我们模拟了生产者和消费者的线程通信机制。生产者线程不断生产产品,而消费者线程不断消费产品。当产品库存满时,生产者等待;当产品库存为空时,消费者等待。

5. 线程池(Executor Service)

线程池是 Java 提供的一个高效的多线程管理工具,它可以避免创建过多的线程,减少系统资源的消耗。Java 中的线程池是通过 ExecutorService 接口来管理的。

5.1 创建线程池

线程池的创建通常使用 Executors 工厂类,它提供了几种常用的线程池:

  • newFixedThreadPool(int n):创建一个固定大小的线程池。
示例:使用 ExecutorService 执行任务
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {// 创建一个固定大小的线程池,池中有 3 个线程ExecutorService executorService = Executors.newFixedThreadPool(3);// 提交多个任务给线程池for (int i = 0; i < 5; i++) {executorService.submit(() -> {System.out.println("Task executed by: " + Thread.currentThread().getName());try {Thread.sleep(1000);  // 模拟任务执行} catch (InterruptedException e) {e.printStackTrace();}});}// 关闭线程池executorService.shutdown();  // 提交完任务后调用 shutdown 来关闭线程池}
}

6. 线程的优先级

Java 允许设置线程的优先级,从而影响线程的调度顺序。线程的优先级是一个整数值,范围从 1 到 10,其中 1 为最低优先级,10 为最高优先级。

示例:设置线程优先级
public class ThreadPriority {public static void main(String[] args) {Thread highPriorityThread = new Thread(() -> {System.out.println("High priority thread is running.");});Thread lowPriorityThread = new Thread(() -> {System.out.println("Low priority thread is running.");});highPriorityThread.setPriority(Thread.MAX_PRIORITY);  // 设置高优先级lowPriorityThread.setPriority(Thread.MIN_PRIORITY);  // 设置低优先级highPriorityThread.start();lowPriorityThread.start();}
}

注意,虽然 Java 提供了线程优先级的设置,但线程调度是由操作系统管理的,不同的操作系统可能会根据自己的调度算法来决定线程的实际执行顺序。

7. 中断线程

线程的中断通常用于停止线程的执行或通知线程需要停止。通过调用线程的 interrupt() 方法可以设置线程的中断标志,而线程可以通过 isInterrupted() 方法来检查自己是否被中断。需要注意的是,interrupt() 并不会立即终止线程,它只是设置线程的中断状态,具体的中断行为需要在线程代码中自行判断并处理。

示例:中断线程
public class InterruptExample {public static void main(String[] args) throws InterruptedException {Thread longRunningThread = new Thread(() -> {try {for (int i = 0; i < 10; i++) {if (Thread.interrupted()) {System.out.println("Thread is interrupted, stopping...");return;  // 响应中断,终止线程}System.out.println("Running... " + i);Thread.sleep(1000);  // 模拟长时间任务}} catch (InterruptedException e) {System.out.println("Thread was interrupted during sleep.");}});longRunningThread.start();// 等待 3 秒后中断线程Thread.sleep(3000);longRunningThread.interrupt();  // 发出中断信号}
}

8. 线程的 join() 方法

join() 方法用于等待一个线程完成。当调用 join() 方法时,当前线程会阻塞,直到目标线程执行完毕为止。它常用于确保某些任务执行完之后再执行其他任务。

示例:使用 join() 等待线程完成
public class JoinExample {public static void main(String[] args) throws InterruptedException {Thread thread1 = new Thread(() -> {try {Thread.sleep(2000);  // 模拟任务执行System.out.println("Thread 1 finished");} catch (InterruptedException e) {e.printStackTrace();}});Thread thread2 = new Thread(() -> {try {Thread.sleep(1000);  // 模拟任务执行System.out.println("Thread 2 finished");} catch (InterruptedException e) {e.printStackTrace();}});thread1.start();thread2.start();// 等待 thread1 和 thread2 完成后再继续执行thread1.join();thread2.join();System.out.println("All threads finished");}
}

在这个例子中,main 线程会等待 thread1thread2 执行完毕后再继续执行。

相关文章:

java中多线程的一些常见操作

Java 中的多线程是通过并发编程来提高应用程序的效率和响应速度。Java 提供了多个机制和类来支持多线程编程&#xff0c;包括继承 Thread 类、实现 Runnable 接口、使用线程池等。以下是 Java 中一些常见的多线程操作和应用场景。 1. 创建线程 1.1 通过继承 Thread 类创建线程…...

【gopher的java学习笔记】什么是Spring - IoC和DI

一聊到java&#xff0c;离不开的一个东西就是spring&#xff1b;当我想了解什么是spring的时候&#xff0c;一查&#xff0c;基本上都是围绕着两个词来展开的&#xff1a;IoC和AOP。 对于我自己来说&#xff0c;AOP我觉得比较好理解&#xff0c;因为不管是之前写golang还是pyt…...

【开源免费】基于SpringBoot+Vue.JS校园社团信息管理系统(JAVA毕业设计)

本文项目编号 T 107 &#xff0c;文末自助获取源码 \color{red}{T107&#xff0c;文末自助获取源码} T107&#xff0c;文末自助获取源码 目录 一、系统介绍二、数据库设计三、配套教程3.1 启动教程3.2 讲解视频3.3 二次开发教程 四、功能截图五、文案资料5.1 选题背景5.2 国内…...

设计模式 创建型 工厂模式(Factory Pattern)与 常见技术框架应用 解析

工厂模式&#xff08;Factory Pattern&#xff09;是一种创建型设计模式&#xff0c;它提供了一种封装对象创建过程的方式&#xff0c;使得对象的创建与使用分离&#xff0c;从而提高了系统的可扩展性和可维护性。 一、核心思想 工厂模式的核心思想是将“实例化对象”的操作与…...

pip 下载安装时使用国内源配置

pip 是 Python 的包管理工具&#xff0c;用于安装和管理第三方库。然而&#xff0c;在某些情况下&#xff0c;默认的 PyPI&#xff08;Python Package Index&#xff09;源可能由于网络原因导致下载速度慢或者连接不稳定。幸运的是&#xff0c;我们可以轻松地配置 pip 使用国内…...

【数据结构】数据结构简要介绍

数据结构是计算机科学中用于组织、管理和存储数据的方式&#xff0c;以便于高效地访问和修改数据。 数据结构的分类&#xff1a; 数据结构可以大致分为两类&#xff1a;线性结构和非线性结构。 1. 线性结构 线性结构中的数据按顺序排列&#xff0c;每个元素有唯一的前驱和后…...

数据分析-Excel

数据类型和函数初步 Excel中有文本类型和数值类型–但是无法用肉眼分辨出来isnumber来区分是否是数值类型text和value函数可以完成数值类型以及文本类型的转换单元格第一位输入’方式明确输入的是文本sum函数必须是数值类型 文本连接-and-or-not-if-mod-max函数 字符串的连接…...

Yocto项目—机器配置文件详解

引言 在Yocto项目中&#xff0c;机器配置文件&#xff08;Machine Configuration File&#xff09;是系统定制化的重要组成部分&#xff0c;直接决定了构建的目标平台硬件特性和能力。本文将深入探讨Yocto项目中的机器配置文件&#xff0c;从其作用、结构到具体配置方法&#…...

30天开发操作系统 第 10 天 -- 叠加处理

前言 得益于昨天的努力&#xff0c;我们终于可以进行内存管理了。不过仔细一看会注意到&#xff0c;bootpack.c都已经有254行了。笔者感觉这段程序太长了&#xff0c;决定整理一下&#xff0c;分出一部分到memory.c中去。(整理中)…好了&#xff0c;整理完了。现在bootpack.c变…...

第十讲 比特币的社会与文化影响

比特币作为一种革命性的数字货币&#xff0c;不仅在经济领域产生了深远的影响&#xff0c;也在社会和文化层面引发了广泛的讨论和变革。本文将探讨比特币如何塑造我们的社会观念、文化趋势以及对未来的展望。 一、比特币与社会观念的变迁 比特币的出现挑战了传统的货币观念和…...

Unity2D无限地图的实现(简单好抄)

说明&#xff1a;本教程实现的是在2D游戏中玩家在游戏中上下左右移动的时候自动进行地图拼接的功能&#xff0c;如果你只想实现左右移动的无限地图&#xff0c;那么这篇博客也能起到一定参考作用。 思路 第一步&#xff1a; 创建一个10*10的2D游戏对象当做地图 第二步创建一个…...

TCP网络编程(一)—— 服务器端模式和客户端模式

这篇文章将会编写基本的服务器网络程序&#xff0c;主要讲解服务器端和客户端代码的原理&#xff0c;至于网络名词很具体的概念&#xff0c;例如什么是TCP协议&#xff0c;不会过多涉及。 首先介绍一下TCP网络编程的两种模式&#xff1a;服务器端和客户端模式&#xff1a; 首先…...

03-类和对象(上)

一、类的概述 1.类的引入 类的封装&#xff1a;将数据和方法封装在一起&#xff0c;加以权限区分&#xff0c;用户只能通过公共方法访问私有数据。 为什么要将数据和方法封装在一起呢&#xff0c;而且还要通过公共方法才能访问私有数据&#xff1f; C语言中数据和方法分开可…...

PCL点云库入门——PCL库点云滤波算法之统计滤波(StatisticalOutlierRemoval)

1、算法原理 统计滤波算法是一种利用统计学原理对点云数据进行处理的方法。它主要通过计算点云中每个点的统计特性&#xff0c;如均值、方差等&#xff0c;来决定是否保留该点。算法首先会设定一个统计阈值&#xff0c;然后对点云中的每个点进行分析。如果一个点的统计特性与周…...

【机器学习】Kaggle实战信用卡反欺诈预测(场景解析、数据预处理、特征工程、模型训练、模型评估与优化)

构建信用卡反欺诈预测模型 建模思路 本项目需解决的问题 本项目通过利用信用卡的历史交易数据&#xff0c;进行机器学习&#xff0c;构建信用卡反欺诈预测模型&#xff0c;提前发现客户信用卡被盗刷的事件。 项目背景 数据集包含由欧洲持卡人于2013年9月使用信用卡进行交的…...

【RISC-V CPU debug 专栏 4 -- RV CSR寄存器介绍】

文章目录 Overview1. CSR寄存器访问指令2. 为何CSR地址不是4字节对齐(1) CSR寄存器空间是独立的地址空间(2) 节省编码空间(3) 对硬件实现的简化 3. CSR的物理大小和对齐无关4. RISC-V 中的 GPR 寄存器及其作用GPR 的详细用途CSR&#xff08;控制状态寄存器&#xff09;与 GPR 的…...

Object.defineProperty() 完整指南

Object.defineProperty() 完整指南 1. 基本概念 Object.defineProperty() 方法允许精确地添加或修改对象的属性。默认情况下&#xff0c;使用此方法添加的属性是不可修改的。 1.1 基本语法 Object.defineProperty(obj, prop, descriptor)参数说明&#xff1a; obj: 要定义…...

postgresql函数创建

postgresql的函数创建 1.创建函数的基本语法&#xff1a; CREATE [OR REPLACE] FUNCTION function_name(parameter_list) RETURNS return_type AS $$ BEGIN -- 函数体 END; $$ LANGUAGE language_name;2.创建函数时传入参数示例:add_user tbl_user表 | id | username | …...

ECMAScript 变量

文章目录 前言一、ECMAScript 变量二、var 关键字1、var 声明作用域2、var 声明提升(hoist)三、let 关键字四、const 关键字🔰 总结前言 任何语言的核心所描述的都是这门语言在最基本的层面上如何工作,涉及 语法、操作符、数据类型以及内置功能,在此基础之上才可以构建复…...

CAN总线波形中最后一位电平偏高或ACK电平偏高问题分析

参考&#xff1a;https://zhuanlan.zhihu.com/p/689336144 有时候看到CAN总线H和L的差值波形的最后一位电平会变高很多&#xff0c;这是什么原因呢&#xff1f; 实际上这是正常的现象&#xff0c;最后一位是ACK位。问题描述为&#xff1a;CAN总线ACK电平偏高。 下面分析下原因…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

什么是库存周转?如何用进销存系统提高库存周转率?

你可能听说过这样一句话&#xff1a; “利润不是赚出来的&#xff0c;是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业&#xff0c;很多企业看着销售不错&#xff0c;账上却没钱、利润也不见了&#xff0c;一翻库存才发现&#xff1a; 一堆卖不动的旧货…...

【单片机期末】单片机系统设计

主要内容&#xff1a;系统状态机&#xff0c;系统时基&#xff0c;系统需求分析&#xff0c;系统构建&#xff0c;系统状态流图 一、题目要求 二、绘制系统状态流图 题目&#xff1a;根据上述描述绘制系统状态流图&#xff0c;注明状态转移条件及方向。 三、利用定时器产生时…...

WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)

一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解&#xff0c;适合用作学习或写简历项目背景说明。 &#x1f9e0; 一、概念简介&#xff1a;Solidity 合约开发 Solidity 是一种专门为 以太坊&#xff08;Ethereum&#xff09;平台编写智能合约的高级编…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

ios苹果系统,js 滑动屏幕、锚定无效

现象&#xff1a;window.addEventListener监听touch无效&#xff0c;划不动屏幕&#xff0c;但是代码逻辑都有执行到。 scrollIntoView也无效。 原因&#xff1a;这是因为 iOS 的触摸事件处理机制和 touch-action: none 的设置有关。ios有太多得交互动作&#xff0c;从而会影响…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

JavaScript 数据类型详解

JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型&#xff08;Primitive&#xff09; 和 对象类型&#xff08;Object&#xff09; 两大类&#xff0c;共 8 种&#xff08;ES11&#xff09;&#xff1a; 一、原始类型&#xff08;7种&#xff09; 1. undefined 定…...

基于Springboot+Vue的办公管理系统

角色&#xff1a; 管理员、员工 技术&#xff1a; 后端: SpringBoot, Vue2, MySQL, Mybatis-Plus 前端: Vue2, Element-UI, Axios, Echarts, Vue-Router 核心功能&#xff1a; 该办公管理系统是一个综合性的企业内部管理平台&#xff0c;旨在提升企业运营效率和员工管理水…...

【网络安全】开源系统getshell漏洞挖掘

审计过程&#xff1a; 在入口文件admin/index.php中&#xff1a; 用户可以通过m,c,a等参数控制加载的文件和方法&#xff0c;在app/system/entrance.php中存在重点代码&#xff1a; 当M_TYPE system并且M_MODULE include时&#xff0c;会设置常量PATH_OWN_FILE为PATH_APP.M_T…...