JAVA--多线程
Java中的多线程是指在同一个Java虚拟机(JVM)中并发执行多个线程的能力。线程是程序执行的最小单元,Java提供了丰富的API来创建和管理线程。以下是Java中实现多线程的一些关键概念和方法:
-
Thread 类:Java提供了
Thread
类来创建和管理线程。通过继承Thread
类并重写其run()
方法,可以定义线程执行的任务。 -
Runnable 接口:Java还提供了
Runnable
接口,它包含一个run()
方法。实现Runnable
接口的类可以被传递给Thread
类的构造器,从而创建一个新的线程。 -
创建线程:可以通过继承
Thread
类或实现Runnable
接口来创建线程。然后,通过调用start()
方法启动线程。 -
生命周期:线程有几种状态,包括新建、就绪、运行、阻塞和死亡。线程状态的变化由线程的生命周期管理。
-
同步:当多个线程访问共享资源时,需要同步以避免数据不一致。Java提供了
synchronized
关键字和ReentrantLock
等同步机制。 -
线程池:Java提供了线程池(
ExecutorService
)来管理线程的创建和销毁,提高资源利用率和执行效率。 -
中断:线程可以被中断,这是线程间通信的一种方式。通过调用线程的
interrupt()
方法可以设置中断状态,而通过检查线程的isInterrupted()
方法可以响应中断。 -
等待/通知机制:Java提供了
wait()
、notify()
和notifyAll()
方法,允许线程在某些条件下等待,或在条件满足时被唤醒。 -
死锁:当多个线程相互等待对方释放资源时,可能会发生死锁。Java提供了工具和方法来检测和避免死锁。
-
并发集合:Java并发包(
java.util.concurrent
)提供了线程安全的集合类,如ConcurrentHashMap
、CopyOnWriteArrayList
等。
下面是一个简单的Java多线程示例,演示了如何创建和启动线程:
// 使用Runnable接口创建线程
class Task implements Runnable {private int taskId;public Task(int id) {this.taskId = id;}@Overridepublic void run() {System.out.println("Task " + taskId + " is running by " + Thread.currentThread().getName());// 执行任务的代码}
}public class MultiThreadExample {public static void main(String[] args) {// 创建线程Thread thread1 = new Thread(new Task(1), "Thread-1");Thread thread2 = new Thread(new Task(2), "Thread-2");// 启动线程thread1.start();thread2.start();}
}
在这个示例中,我们定义了一个Task
类实现了Runnable
接口,并重写了run()
方法来执行任务。然后在main
方法中创建了两个线程,并通过调用它们的start()
方法来启动它们。
Java多线程编程是一个复杂的话题,涉及到线程安全、性能优化、资源管理等多个方面。正确地使用多线程可以提高程序的性能和响应能力,但同时也需要小心处理线程间的交互和同步问题。
在Java中,实现线程间的同步和互斥主要依赖于同步机制,以下是一些常用的方法:
-
synchronized 关键字:
- 可以用来修饰方法或者代码块。
- 当一个线程访问一个对象的
synchronized
方法或者同步代码块时,它会获得这个对象的锁。 - 其他线程必须等待锁释放后才能访问该对象的任何其他
synchronized
方法或同步代码块。
-
wait() 和 notify() 方法:
wait()
方法使当前线程等待,直到其他线程调用相同对象的notify()
或notifyAll()
方法。notify()
唤醒在此对象监视器上等待的单个线程,而notifyAll()
唤醒所有在此对象监视器上等待的线程。
-
Lock 接口和其实现类:
- Java并发API提供了
java.util.concurrent.locks.Lock
接口和一些实现类,如ReentrantLock
。 - 这些锁提供了与
synchronized
关键字类似的功能,但提供了更多的灵活性,例如尝试非阻塞获取锁、可中断的锁获取、超时等待等。
- Java并发API提供了
-
volatile 关键字:
- 确保变量的更新对所有线程立即可见。
- 当一个线程修改了一个
volatile
变量的值,新值会立即同步到主内存中,其他线程可以立即看到这个新值。
-
Atomic 类:
- Java并发API提供了一组原子类,如
AtomicInteger
、AtomicLong
等,它们利用CAS(Compare-And-Swap)操作来保证操作的原子性。
- Java并发API提供了一组原子类,如
-
Concurrent 集合:
java.util.concurrent
包提供了线程安全的集合类,如ConcurrentHashMap
、CopyOnWriteArrayList
等,它们内部实现了同步机制。
-
CountDownLatch、CyclicBarrier、Semaphore 和 Exchanger:
- 这些是Java并发API提供的同步辅助类,用于控制多个线程之间的协调。
下面是一个使用synchronized
关键字和wait()
/notify()
方法实现线程间同步的示例:
public class Counter {private int count = 0;public synchronized void increment() {count++;System.out.println("Count: " + count);// 当计数达到某个值时,通知等待的线程if (count >= 5) {notifyAll();}}public synchronized void waitForCount() throws InterruptedException {while (count < 5) {wait();}}public static void main(String[] args) {Counter counter = new Counter();Thread incrementer = new Thread(() -> {for (int i = 0; i < 10; i++) {counter.increment();}});Thread waiter = new Thread(() -> {try {counter.waitForCount();System.out.println("Count has reached 5 or more.");} catch (InterruptedException e) {e.printStackTrace();}});incrementer.start();waiter.start();}
}
在这个示例中,Counter
类有两个同步方法:increment()
和waitForCount()
。increment()
方法每次被调用时都会增加计数并打印当前计数。如果计数达到5或以上,它会调用notifyAll()
来唤醒等待的线程。waitForCount()
方法使用wait()
来等待计数达到5。
请注意,使用同步机制时,需要小心避免死锁和性能问题。正确的同步策略取决于具体的应用场景和需求。
笔者小,中,大厂均有面试经验,目前正在从事全栈开发工作,坚持每日分享java全栈开发知识与相关的面试真题,希望能够给大家带来帮助,同大家共同进步。
相关文章:
JAVA--多线程
Java中的多线程是指在同一个Java虚拟机(JVM)中并发执行多个线程的能力。线程是程序执行的最小单元,Java提供了丰富的API来创建和管理线程。以下是Java中实现多线程的一些关键概念和方法: Thread 类:Java提供了Thread类…...
ADB-DROM
# 读硬件信息 adb shell "cat /sys/block/mmcblk0/device/name" # MT6767/MT6768/MT6769/MT6762/MT6765/MT6761... # 频率档位 # 固定频率 adb shell "echo 0 > /sys/devices/platform/10012000.dvfsrc/helio-dvfsrc/dvfsrc_force_vcore_dvfs_opp" # …...
mysql 之 explain
1. 查看表的创建字段以及索引情况 show create table user_recommend; 2. 创建索引的原则:列的值比较离散 像性别字段,只有男,女 或者其他;expose字段,只有1分发,0不可分发。就不适宜在这种字段上添加索引…...

CentOS迁移案例 | 保障轨道交通安全、发挥基础设施效能,麒麟信安操作系统支撑某市轨道交通畅行无忧
为缓解城市交通拥堵难题,某市轨道交通公司计划新建一条贯穿城市关键区域、沿路设立20座站点的轨道交通线路,并基于麒麟信安操作系统构建轨道交通信号系统。 轨道交通信号系统是列车核心控制系统,负责列车运行的自动化控制,及对整…...
获取操作系统的信息(Go语言)
在 Go 语言中,你可以使用 runtime 和 os 包来查看操作系统的信息。以下是一些常见的操作系统信息获取方法: 1. 获取操作系统类型和架构信息 Go 的 runtime 包提供了基本的操作系统和架构信息: package mainimport ("fmt""r…...

【论文阅读】HuatuoGPT-II, One-stage Training for Medical Adaption of LLMs
总体概要 本文深入探讨了一款专为医疗领域设计的大规模语言模型——HuatuoGPT-II的创新、性能与应用。HuatuoGPT-II采用统一的单阶段训练流程,将传统的继续预训练和监督微调整合,有效解决了医疗数据的异质性问题,包括语言、体裁和格式差异&a…...
Excel表列序号
题目 给定一个Excel表格中的列名称,返回其相应的列序号。 例如, A -> 1 B -> 2 C -> 3 ... Z -> 26 AA -> 27 AB -> 28 ...示例 1: 输入: "A" 输出: 1示例 2: 输入: "AB" 输出: 28示例 3: 输入: "ZY&…...

IOS 03 纯代码封装自定义View控件
本节将通过纯代码进行封装自定义View控件,以常用的设置页的item为例,实现UI效果如下: 1、创建SettingView继承自UIView import UIKitclass SettingView: UIView {} 2、重写 init() 和 required init?(coder: NSCoder) 方法 纯代码创建Set…...

比较结构加法及其逆运算
在行列可自由变换的平面上有等式 13(3a11)2*4a14a22*4a32*4a44*4a122*4a14 3a11在平面上可能得到6个不同的4点结构,这6个结构的比例为2:1:2:2:4:2. 现在从右向左算,计…...

44.【C语言】指针(重难点)(G)
目录 19.字符指针变量 *定义 *简单说明 *如果是字符串 *像数组一样指定访问常量字符串的字符 *练习 20.数组指针变量 *定义 *格式 *例子 问题1 问题2 *利用指针打印 21.二维数组传参的本质 *回顾 往期推荐 19.字符指针变量 *定义 指向字符的指针变量,用于存储字符…...

746. 使用最小花费爬楼梯-dp3
. - 力扣(LeetCode). - 备战技术面试?力扣提供海量技术面试资源,帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/min-cost-climbing-stairs/description/从左向右填dp表 class Solutio…...

MPU6050详细介绍
一、MPU6050介绍 MPU6050是由三个陀螺仪和三个加速度传感器组成的6轴运动处理组件 内部主要结构:陀螺仪、加速度计、数字运动处理器DMP(Digital Motion Processor) MPU6050有两个IIC接口,第一IIC接口可作为主接口给单片机传输数…...

【分享】Excel的3个隐藏功能
我们在制作Excel表格的时候,有时候会包含一些敏感信息,为了确保这些数据的安全性,Excel提供了隐藏功能来保护工作表,下面小编分享3个Excel常用的隐藏功能,一起来看看如何设置吧! 功能一:隐藏部分…...
Linux中的chown指令
chown(change owner)命令在 Linux 和其他类 Unix 系统中用于更改文件或目录的用户和/或组所有权。 基本用法 chown [选项] 用户名[:组名] 文件或目录 参数说明 用户名:指定新的文件或目录的所有者 组名:可选,指定新…...

UCOSIII内存管理机制详解
目录 前言 1. 内存管理概述 2. 内存区域(存储区)和内存块 3. 存储区控制块(OS_MEM) 4. 内存管理函数 5. 内存碎片问题 6. 注意事项 7.代码实现 7.1创建内存区域 7.2申请内存 7.3释放内存 前言 UCOSIII(即Mi…...

Android12 显示框架之Transaction----client端
目录:Android显示终极宝典 在前面的章节中,应用通过createSurface()在surfaceflinger中创建了一层layer,紧接着要做的事情就是对这个layer设置一些属性(或者叫状态),常设置的属性有位置、大小、z-order等等…...
在Windows上使用FRP搭建内网穿透:
FRP服务器端配置(公网服务器) 下载FRP: 访问FRP的GitHub发布页面:https://github.com/fatedier/frp/releases下载对应系统架构的frp_<version>_linux_amd64.tar.gz(如果你的服务器是Linux系统)或者f…...

TypeError: Cannot read properties of undefined (reading ‘scrollIntoView‘)(已解决)
问题复现:眨眼睛使用vitevue3实现跳转dom功能时使用了scrollIntoView方法,在打包上传以后使用该功能报错 小友可能会陷入误区,以为是函数方法有问题,毕竟在开发时是没有问题的, 而实际上呢问题出在获取节点失败了 在这…...

【解决】Unity Inspector 视窗脚本中文乱码问题
开发平台:Unity 2020 编程平台:Visual Studio 2022 问题描述 开发过程中,为便利化快速审阅代码内容,通过 Unity Inspector 确认代码内容与逻辑。但对于默认安装的 Visual Studio 编程平台,保存的 UTF- 8 脚本文件在…...

使用 C/C++访问 MySQL
目录 准备工作 尝试链接 MySQL Client MySQL 接口介绍 准备工作 保证 MySQL 服务有效。下载MySQL开发包(可以在MySQL官网下载安装也可以在软件源安装) MySQL 开发包通常会包含一些特定的头文件和库文件。您可以检查以下常见的路径: /us…...

UE5 学习系列(二)用户操作界面及介绍
这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…...
[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?
🧠 智能合约中的数据是如何在区块链中保持一致的? 为什么所有区块链节点都能得出相同结果?合约调用这么复杂,状态真能保持一致吗?本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
将对透视变换后的图像使用Otsu进行阈值化,来分离黑色和白色像素。这句话中的Otsu是什么意思?
Otsu 是一种自动阈值化方法,用于将图像分割为前景和背景。它通过最小化图像的类内方差或等价地最大化类间方差来选择最佳阈值。这种方法特别适用于图像的二值化处理,能够自动确定一个阈值,将图像中的像素分为黑色和白色两类。 Otsu 方法的原…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...