# Java中多线程和线程安全是什么 ## 目录 1. [多线程基础概念](#一多线程基础概念) - 1.1 [什么是线程](#11-什么是线程) - 1.2 [线程与进程的区别](#12-线程与进程的区别) - 1.3 [为什么需要多线程](#13-为什么需要多线程) 2. [Java中的线程实现](#二java中的线程实现) - 2.1 [继承Thread类](#21-继承thread类) - 2.2 [实现Runnable接口](#22-实现runnable接口) - 2.3 [实现Callable接口](#23-实现callable接口) - 2.4 [三种方式对比](#24-三种方式对比) 3. [线程生命周期](#三线程生命周期) - 3.1 [线程状态图解](#31-线程状态图解) - 3.2 [状态转换详解](#32-状态转换详解) 4. [线程安全核心问题](#四线程安全核心问题) - 4.1 [原子性问题](#41-原子性问题) - 4.2 [可见性问题](#42-可见性问题) - 4.3 [有序性问题](#43-有序性问题) 5. [线程安全解决方案](#五线程安全解决方案) - 5.1 [synchronized关键字](#51-synchronized关键字) - 5.2 [Lock接口](#52-lock接口) - 5.3 [volatile关键字](#53-volatile关键字) - 5.4 [原子类](#54-原子类) - 5.5 [ThreadLocal](#55-threadlocal) 6. [并发工具类](#六并发工具类) - 6.1 [CountDownLatch](#61-countdownlatch) - 6.2 [CyclicBarrier](#62-cyclicbarrier) - 6.3 [Semaphore](#63-semaphore) 7. [线程池技术](#七线程池技术) - 7.1 [Executor框架](#71-executor框架) - 7.2 [ThreadPoolExecutor](#72-threadpoolexecutor) - 7.3 [合理配置线程池](#73-合理配置线程池) 8. [实际应用场景](#八实际应用场景) - 8.1 [高并发计数器](#81-高并发计数器) - 8.2 [生产者消费者模式](#82-生产者消费者模式) 9. [总结与最佳实践](#九总结与最佳实践) ## 一、多线程基础概念 ### 1.1 什么是线程 线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。在Java中,每个线程都拥有独立的程序计数器、虚拟机栈和本地方法栈,但共享堆内存和方法区资源。 ```java // 最简单的线程示例 Thread thread = new Thread(() -> { System.out.println("线程执行中..."); }); thread.start();
对比维度 | 进程 | 线程 |
---|---|---|
资源占用 | 独立内存空间 | 共享进程内存 |
创建开销 | 较大(需分配系统资源) | 较小 |
通信方式 | 管道、信号、套接字等 | 共享变量 |
稳定性 | 一个崩溃不影响其他进程 | 一个崩溃可能导致进程终止 |
class MyThread extends Thread { @Override public void run() { System.out.println("继承Thread类实现的线程"); } } // 使用方式 new MyThread().start();
class MyRunnable implements Runnable { @Override public void run() { System.out.println("实现Runnable接口的线程"); } } // 使用方式 new Thread(new MyRunnable()).start();
class MyCallable implements Callable<String> { @Override public String call() throws Exception { return "带返回值的线程"; } } // 使用方式 FutureTask<String> task = new FutureTask<>(new MyCallable()); new Thread(task).start(); System.out.println(task.get()); // 获取返回值
实现方式 | 优点 | 缺点 |
---|---|---|
继承Thread | 编码简单 | 无法继承其他类 |
实现Runnable | 可继承其他类,更灵活 | 无返回值 |
实现Callable | 可获取返回值,支持异常 | 使用稍复杂 |
stateDiagram [*] --> NEW NEW --> RUNNABLE: start() RUNNABLE --> BLOCKED: 等待同步锁 BLOCKED --> RUNNABLE: 获取锁 RUNNABLE --> WTING: wait()/join() WTING --> RUNNABLE: notify()/notifyAll() RUNNABLE --> TIMED_WTING: sleep(n)/wait(n) TIMED_WTING --> RUNNABLE: 超时结束 RUNNABLE --> TERMINATED: run()结束
// 非原子操作示例 private int count = 0; public void increment() { count++; // 实际包含读-改-写三步操作 }
// 可见性问题示例 boolean flag = true; // 线程A new Thread(() -> { while(flag) { // 可能永远循环 } }).start(); // 线程B new Thread(() -> { flag = false; }).start();
// 指令重排可能导致的问题 int a = 0; boolean flag = false; // 线程A a = 1; // 语句1 flag = true; // 语句2 // 线程B if(flag) { // 语句3 int i = a; // 语句4 }
// 同步方法 public synchronized void syncMethod() { // 临界区代码 } // 同步代码块 public void syncBlock() { synchronized(this) { // 临界区代码 } } // 静态方法锁 public static synchronized void staticSync() { // 锁的是Class对象 }
// ReentrantLock使用示例 private final Lock lock = new ReentrantLock(); public void lockExample() { lock.lock(); try { // 临界区代码 } finally { lock.unlock(); } }
// 保证可见性示例 private volatile boolean shutdown; public void shutdown() { shutdown = true; } public void doWork() { while(!shutdown) { // 执行任务 } }
// AtomicInteger使用示例 private AtomicInteger counter = new AtomicInteger(0); public void safeIncrement() { counter.incrementAndGet(); // 原子操作 }
// 线程局部变量示例 private static ThreadLocal<SimpleDateFormat> dateFormat = ThreadLocal.withInitial(() -> new SimpleDateFormat("yyyy-MM-dd")); public String formatDate(Date date) { return dateFormat.get().format(date); }
(由于篇幅限制,后续章节内容将简要概述,实际完整文章应详细展开每个技术点)
完整文章建议扩展方向: 1. 每个代码示例添加详细注释 2. 增加性能对比测试数据 3. 补充JMM内存模型原理图 4. 添加实际项目案例说明 5. 深入分析synchronized锁升级过程 6. 讨论分布式环境下的线程安全问题 “`
注:此大纲结构完整,实际撰写时需要: 1. 补充更多代码示例和注释 2. 添加示意图和流程图 3. 插入性能对比表格 4. 增加实际案例解析 5. 每个技术点进行优缺点分析 6. 最终字数通过扩展各小节内容达到6450字左右
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。