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

Java—多线程

Java线程安全体现在三方面:

  • 原子性:提供互斥访问,同一时刻只能有一个线程对数据进行操作,在Java中使用了atomic包和synchronized关键字来确保原子性
  • 可见性:一个线程对主内存的修改可以及时地被其他线程看到,在Java中使用volatile关键字确保可见性
  • 有序性:由于指令重排,线程中的代码执行可能是无需的,Java通过happens-before原则来确保有序性

线程创建方式:

1、继承Thread类并重写run方法

  • 优点:编写简单,访问当前线程时可直接使用this获取
  • 缺点:无法再继承其他父类

2、实现Runnable接口并重写run方法,后作为参数传递给Thread类

  • 优点:可以继承其他父类
  • 缺点:需要使用Thread.currentThread()方法获取当前线程

3、实现Callable接口创建FutureTask,FutureTask作为参数传递给Thread类

class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {// 线程执行的代码,这里返回一个整型结果return 1;}
}public static void main(String[] args) {MyCallable task = new MyCallable();FutureTask<Integer> futureTask = new FutureTask<>(task);Thread t = new Thread(futureTask);t.start();try {Integer result = futureTask.get();  // 获取线程执行结果System.out.println("Result: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();}
}
  • 优点:可以调用futureTask,get()方法获取返回值,可以继承多个父类
  • 缺点:编程复杂

Java线程状态有哪些?

线程状态解释
NEW尚未启动的线程状态,即线程创建,还未调用start方法
RUNNABLE就绪状态(调用start,等待调度)+正在运行
BLOCKED等待监视器锁时,陷入阻塞状态
WAITING调用wait方法进入等待,等待状态的线程正在等待另一线程执行特定的操作(如notify)
TIMED_WAITING调用sleep方法,具有指定等待时间的等待状态
TERMINATED线程完成执行,终止状态

sleep和wait方法的区别:

特性sleep()wait()
所属类Thread 类(静态方法)Object 类(实例方法)
锁释放
使用前提任意位置调用必须在同步块内(持有锁)
唤醒机制超时自动恢复(Timed_Waiting)需 notify()/notifyAll() 或超时
设计用途暂停线程执行,不涉及锁协作线程间协调,释放锁让其他线程工作

调用sleep方法会主动让出CPU时间片,但不会释放线程已持有的锁,可能导致其他竞争线程阻塞。

blocked和waiting状态的区别:

特性blockedwaiting
触发条件锁竞争失败,被动触发阻塞直到锁可用主动调用wait、join或park方法
唤醒机制锁释放时自动唤醒调用Object.notyfi()/notifyAll()唤醒

notify和notifyAll的区别?

  • notify:唤醒一个线程(具体策略由jvm实现,例如hotspot是以先进先出的顺序唤醒),其他线程依然处于等待状态,若唤醒的线程没有继续调用notify,则其他线程只能等待超时或被中断 
  • notifyAll:所有线程退出待唤醒状态,开始竞争锁

线程通信(volatile与synchronized区别)

使用volatile修饰,使所有线程可即时察觉到变量的变化

  • 写入时会将变量直接写入到主内存中
  • 读取时会直接前往主内存读取变量
  • 通过绕过工作内存实现
  • 优点:避免变量暂存到线程独享的工作内存中,或一直读取工作内存中的数据
  • 缺点:无法确保写入操作的原子性,不能确保并发安全

使用synchronized

  • 线程进入同步代码块时,清空工作内存,重新在主内存中加载变量数据
  • 线程离开同步代码块时,将工作内存的变量强制刷新到主内存中
  • 通过Monitor实现
  • 优点:确保原子性和变量的可见性
  • 缺点:依赖操作系统底层互斥和线程上下文切换,性能开销较大

线程中断方法:

方法适用场景注意事项
循环检测标志位简单无阻塞的逻辑确保标志位使用 volatile 或通过锁保证可见性
中断机制可中断的阻塞操作正确处理 InterruptedException 并恢复中断标志
Future.cancel()线程池管理任务需要线程池任务支持中断处理机制
资源关闭不可中断的阻塞操作(如Sockets)显式关闭资源触发异常,结合中断状态判断回滚

自定义标志位:

public class SafeStopWithFlag implements Runnable {// 使用 volatile 保证可见性private volatile boolean running = true;@Overridepublic void run() {while (running) {// 处理任务逻辑System.out.println("Thread is running...");Thread.sleep(1000)    }System.out.println("Thread terminated safely.");}// 停止线程的方法(由外部调用)public void stop() {running = false;}
}

线程中断机制:

public class InterruptExample implements Runnable {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {try {System.out.println("Working...");Thread.sleep(1000);} catch (InterruptedException e) {// 当阻塞时被中断,抛出异常并清除中断状态System.out.println("Interrupted during sleep!");Thread.currentThread().interrupt(); // 重新设置中断标志}}System.out.println("Thread terminated by interrupt.");}
}

Future取消任务:

public class FutureCancelDemo {public static void main(String[] args) {ExecutorService executor = Executors.newSingleThreadExecutor();Future<?> future = executor.submit(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("Task running...");try {Thread.sleep(1000);} catch (InterruptedException e) {System.out.println("Task interrupted.");Thread.currentThread().interrupt();}}});try {Thread.sleep(3000);future.cancel(true); // true表示尝试中断任务线程} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {executor.shutdown();}}
}

遇到同步操作或I/O连接的不可中断阻塞操作:

public class SocketHandler implements Runnable {private ServerSocket serverSocket;public SocketHandler(ServerSocket serverSocket) {this.serverSocket = serverSocket;}@Overridepublic void run() {try {// serverSocket.accept()阻塞时无法响应中断while (!Thread.currentThread().isInterrupted()) {Socket socket = serverSocket.accept();// 处理连接...}} catch (IOException e) {if (Thread.currentThread().isInterrupted()) {System.out.println("Thread stopped by interrupt.");}}}// 特殊关闭方法(销毁资源)public void stop() {try {serverSocket.close(); // 关闭资源使accept()抛出异常} catch (IOException e) {System.out.println("Error closing socket: " + e);}}
}
http://www.xdnf.cn/news/9625.html

相关文章:

  • 如何使用 poetry 创建虚拟环境,VSCode 如何激活使用 Poetry 虚拟环境(VSCode如何配置 Poetry 虚拟环境)
  • MVCC原理解析
  • js 手写promise
  • 专栏更新通知
  • Python 科学计算有哪些提高运算速度的技巧
  • 力扣——1.两数之和
  • 【论文阅读】User Diverse Preference Modeling by Multimodal Attentive Metric Learning
  • 【笔记】修改abu量化本地部署数据文件夹目录
  • OpenCV CUDA模块直方图计算------用于在 GPU 上执行对比度受限的自适应直方图均衡类cv::cuda::CLAHE
  • Python 的 `next()`函数
  • 数字化回归本质:第一性原理驱动的制造业转型与AI+云PLM系统实践
  • LeetCode-数组技巧题目
  • 影刀RPA-20-高级操作题2
  • 后端思维之高并发处理方案
  • 使用LSTM对销售数据进行预测
  • 简乐 1.4.0 | 非常简洁 无损下载 畅听全网
  • 聊一聊 C# NativeAOT 多平台下的函数导出
  • Milvus向量Search查询综合案例实战(下)
  • Telnet 命令详解
  • 深度学习---注意力机制(Attention Mechanism)
  • docker 网络-用户定义网络
  • 【OCSA 2025】征稿通道已经开启​
  • 【连接器专题】 EIA-364 系列标准的完整列表
  • 加减数值策略
  • 【笔记】修复ImportError: cannot import name ‘Mapping‘ from ‘collections‘
  • DeepSpeed常见面试问题
  • PMO价值重构:从项目管理“交付机器”到“战略推手”
  • 消防应急装备管理:打造消防营区智能仓储
  • 36. 编写异步webdriver接口请求客户端
  • Vector - VT System - 板卡_VT板卡使用介绍_08