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

Java多线程基础详解:从实现到线程安全

一、Thread与Runnable实现方式对比

1.1 继承Thread类实现多线程

class MyThread extends Thread {@Overridepublic void run() {System.out.println("Thread running: " + Thread.currentThread().getName());}
}public class ThreadDemo {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();t1.start();t2.start();}
}

特点

  • 直接继承Thread类并重写run()
  • 每个线程对象独立运行,资源共享需额外处理
  • 受单继承限制,扩展性较弱

1.2 实现Runnable接口方式

class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("Runnable running: " + Thread.currentThread().getName());}
}public class RunnableDemo {public static void main(String[] args) {MyRunnable task = new MyRunnable();new Thread(task, "Thread-1").start();new Thread(task, "Thread-2").start();}
}

优势

  • 避免单继承限制,保持类设计灵活性
  • 同一任务对象可被多个线程共享
  • 更符合"组合优于继承"的设计原则

1.3 关键对比

特性Thread类Runnable接口
实现方式继承类实现接口
资源共享需独立实例可共享实例
锁机制对象锁需显式同步
线程池适配需转换为Runnable直接适配

二、sleep()与wait()深度解析

2.1 核心区别对比

特性sleep()wait()
方法归属Thread类(静态方法)Object类(实例方法)
锁行为不释放锁释放对象锁
唤醒机制时间到期自动唤醒需notify()/notifyAll()
使用场景定时任务/延迟操作线程协作/条件等待
异常处理抛出InterruptedException同上

2.2 典型使用场景

sleep()示例(定时任务)

// 每秒执行一次任务
while (true) {processTask();try {Thread.sleep(1000);} catch (InterruptedException e) {Thread.currentThread().interrupt();}
}

wait()示例(生产者-消费者)

class SharedQueue {private final List<Object> queue = new ArrayList<>();public synchronized void put(Object obj) {while (queue.size() == MAX_SIZE) {try {wait(); // 队列满时等待} catch (InterruptedException e) {}}queue.add(obj);notifyAll();}public synchronized Object take() {while (queue.isEmpty()) {try {wait(); // 队列空时等待} catch (InterruptedException e) {}}Object obj = queue.remove(0);notifyAll();return obj;}
}

2.3 注意事项

  1. wait()必须在同步代码块内调用
  2. 优先使用notifyAll()而非notify()避免死锁
  3. sleep()时间精度受系统调度影响
  4. 避免在循环外使用wait()

三、线程安全经典案例分析

3.1 非原子操作引发的问题

class Counter {private int count = 0;public void increment() {count++; // 非原子操作(load→add→store)}public int getCount() {return count;}
}public class UnsafeDemo {public static void main(String[] args) throws InterruptedException {Counter counter = new Counter();Thread t1 = new Thread(() -> {for (int i = 0; i < 10000; i++) {counter.increment();}});Thread t2 = new Thread(() -> {for (int i = 0; i < 10000; i++) {counter.increment();}});t1.start();t2.start();t1.join();t2.join();System.out.println("Final count: " + counter.getCount()); // 可能小于20000}
}

3.2 解决方案对比

同步方法

public synchronized void increment() {count++;
}

同步代码块

public void increment() {synchronized (this) {count++;}
}

原子类

import java.util.concurrent.atomic.AtomicInteger;class SafeCounter {private AtomicInteger count = new AtomicInteger(0);public void increment() {count.incrementAndGet();}public int getCount() {return count.get();}
}

3.3 性能优化策略

  1. 缩小同步范围
// 不推荐
public synchronized void process() {// 非共享操作...count++;
}// 推荐
public void process() {// 非共享操作...synchronized (this) {count++;}
}
  1. 锁分离技术
class AdvancedCounter {private final Object readLock = new Object();private final Object writeLock = new Object();private int count = 0;public void increment() {synchronized (writeLock) {count++;}}public int getCount() {synchronized (readLock) {return count;}}
}
  1. 使用并发容器
// 替代synchronizedList
List<String> list = new CopyOnWriteArrayList<>();// 替代synchronizedMap
Map<String, Integer> map = new ConcurrentHashMap<>();

四、多线程最佳实践

  1. 优先使用Runnable接口实现多线程
  2. 尽可能缩小同步代码块范围
  3. 优先使用并发工具类替代synchronized
  4. 避免在循环外使用wait()/notify()
  5. 合理使用线程池管理线程生命周期
  6. 对竞争资源使用原子类操作
  7. 始终考虑线程安全问题,即使看似安全的只读操作

通过本文的系统讲解,相信读者已经掌握了Java多线程编程的核心概念和实战技巧。在实际开发中,建议结合JUC包中的高级并发工具(如Lock、Semaphore、CountDownLatch等)来构建更高效稳定的多线程应用。

http://www.xdnf.cn/news/15967.html

相关文章:

  • CS231n-2017 Lecture2图像分类笔记
  • Map集合
  • C++入门--lesson4
  • 嵌入式学习-PyTorch(9)-day25
  • HTTPHTTPSTLSDNSRSA
  • Python技术题2
  • 工程图矢量化 笔记 | potrace ezdxf svgpathtools | png转svg保存dxf用matplotlib画出来
  • 如何构建未来的人-AI-环境智能教育生态系统
  • 线性回归问题
  • xss的利用
  • 《YOLOv13魔术师专栏》全景指南:从理论到工业级实战
  • ICT测试原理之--什么是假短
  • JavaSE-接口
  • Android14 SystemUI 启动流程(2)
  • 笔试大题20分值(用两个栈实现队列)
  • Unity物理响应函数与触发器
  • C++类和对象(一)基础内容讲解
  • 2025暑假训练树状数组
  • 自动化立体仓库堆垛机控制系统上报堆垛机状态 FC5
  • MySQL 写入性能优化全攻略(附 GitHub 面试题项目链接)
  • 最终分配算法【论文材料】
  • laravel RedisException: Connection refused优雅草PMS项目管理系统报错解决-以及Redis 详细指南-优雅草卓伊凡
  • WSL的功能及用途
  • JavaScript空值安全深度指南
  • 单调队列深度解析(下)
  • 前端开发技巧:浏览器模拟弱网络环境
  • 【Linux】重生之从零开始学习运维之Nginx
  • 高可用架构设计与实践综述
  • XSS总结
  • 【RK3576】【Android14】固件烧录