当前位置: 首页 > 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电平偏高。 下面分析下原因…...

P4084 [USACO17DEC] Barn Painting G 题解

题目描述Farmer John 有一个大农场&#xff0c;农场上有 N 个谷仓&#xff08;1≤N≤105&#xff09;&#xff0c;其中一些已经涂色&#xff0c;另一些尚未涂色。Farmer John 想要为这些剩余的谷仓涂色&#xff0c;使得所有谷仓都被涂色&#xff0c;但他只有三种可用的油漆颜色…...

AIGlasses_for_navigation 的Java后端集成:SpringBoot微服务调用实战

AIGlasses_for_navigation 的Java后端集成&#xff1a;SpringBoot微服务调用实战 最近在做一个物流仓储的智能调度项目&#xff0c;里面用到了不少视觉导航的AGV小车。为了让这些小车更“聪明”&#xff0c;我们尝试引入了一套叫AIGlasses_for_navigation的视觉导航模型。这东…...

一维dp知识点

1.一维DP的核心&#xff1a;用一维数组 dp[i] 记录状态&#xff0c;通过清晰的递推关系&#xff08;状态转移&#xff09;求解。2. 基础模型&#xff1a;线性递推核心是找到 dp[i] 和 dp[i-1]、dp[i-2] 的关系。爬楼梯&#xff1a;dp[i] dp[i-1] dp[i-2] 最小花费爬楼梯&…...

KCD Beijing 2026 分享回顾:从 Device Plugin 到 DRA——GPU 调度范式升级与 HAMi-DRA 实践

KCD Beijing 2026 是近年来规模最大的 Kubernetes 社区大会之一&#xff0c;超过 1000 人报名参与&#xff0c;刷新了历届 KCD 北京的记录。HAMi 社区不仅受邀进行了技术分享&#xff0c;也在现场设立了展台&#xff0c;与来自云原生与 AI 基础设施领域的开发者和企业用户进行了…...

YOLO X Layout快速部署:Docker一键启动,开箱即用

YOLO X Layout快速部署&#xff1a;Docker一键启动&#xff0c;开箱即用 1. 简介与核心价值 你是否经常需要处理大量文档图片&#xff0c;却苦于手动标注各种元素区域&#xff1f;YOLO X Layout正是为解决这个问题而生的智能工具。它能自动识别文档中的文本、表格、图片、标题…...

bert-base-chinese新手必看:完形填空与语义相似度功能实测教程

bert-base-chinese新手必看&#xff1a;完形填空与语义相似度功能实测教程 1. 快速了解bert-base-chinese bert-base-chinese是Google发布的经典中文预训练模型&#xff0c;作为NLP领域的基础模型&#xff0c;它已经成为中文自然语言处理任务的标准选择之一。这个模型特别适合…...

OpenClaw技能组合:用Qwen2.5-VL-7B+OCR实现全自动发票报销

OpenClaw技能组合&#xff1a;用Qwen2.5-VL-7BOCR实现全自动发票报销 1. 为什么需要自动化发票报销 每次月底整理发票都让我头疼——需要手动截图、识别金额、填写报销单、发送邮件。直到我发现OpenClaw可以通过组合多个技能模块&#xff0c;实现从截图识别到财务审核的全流程…...

如何组合seo关键词

如何组合SEO关键词 在当今的数字营销环境中&#xff0c;如何组合SEO关键词成为了每一个网站运营者的首要任务。这不仅决定了网站的可见度&#xff0c;还直接影响到流量和最终的转化率。本文将详细探讨如何组合SEO关键词&#xff0c;以实现最佳的搜索引擎优化效果。 什么是SEO…...

FocalNet目标检测、实例分割模型环境配置FocalNet目标检测、实例分割模型数据集调整FocalNet目标检测、实例分割模型代跑训练FocalNet目标检测、实例分割改进创新Focal

FocalNet目标检测、实例分割模型环境配置 FocalNet目标检测、实例分割模型数据集调整 FocalNet目标检测、实例分割模型代跑训练 FocalNet目标检测、实例分割改进创新 FocalNet环境配置&#xff1a;Windows、Ubuntu、Centos、Macos等系统环境&#xff0c;如果电脑拥有显卡&#…...

YOLO X Layout在新闻行业的应用:版面自动排版

YOLO X Layout在新闻行业的应用&#xff1a;版面自动排版 每天清晨&#xff0c;当大多数人还在睡梦中时&#xff0c;新闻编辑部的排版编辑已经开始了一天中最紧张的工作&#xff1a;将记者们连夜赶制的稿件、摄影师捕捉的精彩瞬间、设计师制作的图表&#xff0c;精准地排列在有…...