您好,登录后才能下订单哦!
# Java中怎么实现多线程
## 目录
1. [多线程基础概念](#一多线程基础概念)
- 1.1 [进程与线程的区别](#11-进程与线程的区别)
- 1.2 [多线程的优势与风险](#12-多线程的优势与风险)
2. [Java多线程实现方式](#二java多线程实现方式)
- 2.1 [继承Thread类](#21-继承thread类)
- 2.2 [实现Runnable接口](#22-实现runnable接口)
- 2.3 [实现Callable接口](#23-实现callable接口)
- 2.4 [使用线程池](#24-使用线程池)
3. [线程生命周期与状态转换](#三线程生命周期与状态转换)
4. [线程同步与锁机制](#四线程同步与锁机制)
- 4.1 [synchronized关键字](#41-synchronized关键字)
- 4.2 [Lock接口](#42-lock接口)
5. [线程间通信](#五线程间通信)
- 5.1 [wait/notify机制](#51-waitnotify机制)
- 5.2 [Condition对象](#52-condition对象)
6. [高级多线程特性](#六高级多线程特性)
- 6.1 [volatile关键字](#61-volatile关键字)
- 6.2 [ThreadLocal类](#62-threadlocal类)
7. [实际应用场景](#七实际应用场景)
8. [常见问题与解决方案](#八常见问题与解决方案)
---
## 一、多线程基础概念
### 1.1 进程与线程的区别
| 特性 | 进程 | 线程 |
|------------|------------------------|--------------------------|
| 资源占用 | 独立内存空间 | 共享进程内存 |
| 创建开销 | 大(需复制父进程资源) | 小(共享现有资源) |
| 通信方式 | IPC(管道、信号等) | 直接读写共享变量 |
| 稳定性 | 一个崩溃不影响其他 | 线程崩溃可能导致进程终止 |
### 1.2 多线程的优势与风险
**优势:**
- 提高CPU利用率(特别是在多核处理器上)
- 提升系统吞吐量(I/O操作时不阻塞主线程)
- 改善用户体验(GUI程序保持响应)
**风险:**
- 线程安全问题(竞态条件、数据不一致)
- 死锁风险(多个线程互相等待)
- 调试难度大(非确定性执行顺序)
---
## 二、Java多线程实现方式
### 2.1 继承Thread类
```java
class MyThread extends Thread {
@Override
public void run() {
System.out.println("Thread running: " + Thread.currentThread().getName());
}
}
// 使用方式
MyThread thread = new MyThread();
thread.start(); // 注意:调用run()是普通方法调用,start()才是启动线程
特点: - 简单直接 - 无法继承其他类(Java单继承限制) - 线程与任务耦合
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("Runnable running: " + Thread.currentThread().getName());
}
}
// 使用方式
Thread thread = new Thread(new MyRunnable());
thread.start();
优势: - 实现接口不影响继承其他类 - 任务与线程解耦 - 便于线程池管理
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "Callable result: " + Thread.currentThread().getName();
}
}
// 使用方式
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<String> future = executor.submit(new MyCallable());
System.out.println(future.get()); // 获取返回值
executor.shutdown();
特点: - 可以返回结果(通过Future对象获取) - 能抛出受检异常 - 通常配合ExecutorService使用
ExecutorService threadPool = Executors.newFixedThreadPool(5);
// 提交任务
threadPool.execute(() -> {
System.out.println("Lambda Runnable: " + Thread.currentThread().getName());
});
// 关闭线程池
threadPool.shutdown();
推荐实践:
- 避免直接创建线程(使用线程池减少开销)
- 根据场景选择线程池类型:
- newCachedThreadPool
:弹性线程数
- newFixedThreadPool
:固定线程数
- newScheduledThreadPool
:定时任务
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()结束
// 同步方法
public synchronized void syncMethod() {
// 临界区代码
}
// 同步块
public void syncBlock() {
synchronized(this) {
// 临界区代码
}
}
锁特性: - 可重入性:线程可重复获取已持有的锁 - 非公平锁:不保证等待线程的获取顺序
Lock lock = new ReentrantLock();
void safeMethod() {
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock(); // 必须手动释放
}
}
优势:
- 可中断锁(lockInterruptibly()
)
- 尝试获取锁(tryLock()
)
- 公平锁选项(new ReentrantLock(true)
)
synchronized(sharedObject) {
while(conditionNotMet) {
sharedObject.wait(); // 释放锁并等待
}
// 执行操作
sharedObject.notifyAll(); // 唤醒等待线程
}
注意要点:
- 必须在同步块中使用
- 推荐使用notifyAll()
而非notify()
- 判断条件使用while而非if(防止虚假唤醒)
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
// 等待方
lock.lock();
try {
while(conditionNotMet) {
condition.await();
}
} finally {
lock.unlock();
}
// 通知方
lock.lock();
try {
condition.signalAll();
} finally {
lock.unlock();
}
private volatile boolean flag = false;
// 线程1
flag = true; // 保证对其他线程立即可见
// 线程2
while(!flag) { /*...*/ }
作用: - 保证变量可见性(禁止CPU缓存) - 禁止指令重排序(内存屏障)
注意: - 不保证原子性(复合操作仍需同步)
ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);
// 每个线程独立副本
threadLocal.set(threadLocal.get() + 1);
典型应用场景: - 数据库连接管理 - 用户会话信息存储 - 避免参数透传
问题1:如何避免死锁?
- 解决方案:按固定顺序获取多把锁,使用tryLock
设置超时
问题2:线程池参数如何配置? - CPU密集型:核心线程数 = CPU核数 + 1 - I/O密集型:核心线程数 = CPU核数 * (1 + 平均等待时间/平均计算时间)
问题3:如何处理线程未捕获异常?
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
System.err.println("Exception in thread " + t.getName() + ": " + e);
});
性能优化建议:
- 使用ConcurrentHashMap
替代同步的HashMap
- 考虑使用ReadWriteLock
优化读多写少场景
- 优先使用java.util.concurrent
包中的并发工具类
本文总结了Java多线程编程的核心知识点,实际开发中应根据具体场景选择合适的并发策略。建议通过《Java并发编程实战》等专业书籍深入理解并发原理。 “`
注:本文实际约3800字,完整扩展到4100字可增加以下内容: 1. 每种实现方式的更多代码示例 2. 性能对比测试数据 3. JDK8+的新特性(如CompletableFuture) 4. 更多实际案例的详细分析 5. JVM层面线程实现的原理说明
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。