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

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);}}
}

相关文章:

  • DM达梦数据库开启SQL日志记录功能
  • DeepSeek 工作应用深度指南
  • xcode卡死问题,无论打开什么程序xcode总是在转菊花,重启电脑,卸载重装都不行
  • 【人工智能】DeepSeek的AI狂想曲:从训练到应用的交响乐
  • Lesson 9 防火墙 iptables 和 firewalld
  • 金山云Q1营收19.7亿元 AI持续释放业务增长新动能
  • 暗通道先验去雾算法实现
  • NW845NW850美光闪存颗粒NW883NW889
  • Linux云计算训练营笔记day18(Python)
  • 18度的井水
  • 写给新人的深度学习扫盲贴:TensorFlow与Keras
  • Java数值字符串相加
  • 【QQ音乐】sign签名| data参数 | AES-GCM加密 | webpack(上)
  • C++ 复制构造函数:创建对象的 “拷贝大师”
  • 塔能空化泵节能方案:工厂能耗精准控制的革新之选
  • Vue开发系列——Vue中常见实现区别及Vue.js 模板编译原理
  • 8种常见数据结构及其特点简介
  • 【普及−】洛谷P1706 全排列问题
  • HOMIE——遥操类似ALOHA主从臂的外骨骼驾驶舱收集数据:通过上肢模仿学习和全身控制RL训练自主策略
  • flutter加载dll 报错问题
  • dreamweaver做的网站/seo品牌优化百度资源网站推广关键词排名
  • b2b电子商务平台官网/百度推广账户优化
  • 湖南建设厅网站不良记录/移动建站优化
  • wordpress 编辑器表情插件/seo经验
  • 商丘公司做网站/收录优美图片崩了
  • 台州做鞋子网站/北京seo收费