5.6 KiB
5.6 KiB
线程基础
目录
线程概念
进程 vs 线程
// 进程:程序执行的基本单位
// - 有独立的内存空间
// - 进程间通信复杂
// 线程:CPU 调度的基本单位
// - 共享进程的内存空间
// - 线程间通信简单
主线程 vs 子线程
// 主线程(UI 线程)
// - 负责 UI 更新
// - 不能执行耗时操作
// - 阻塞会导致 ANR
// 子线程(工作线程)
// - 执行耗时操作
// - 不能直接更新 UI
// - 需要通过 Handler 更新 UI
线程创建
方式1:继承 Thread
public class MyThread extends Thread {
@Override
public void run() {
// 线程执行代码
System.out.println("Thread running");
}
}
// 使用
MyThread thread = new MyThread();
thread.start();
方式2:实现 Runnable
public class MyRunnable implements Runnable {
@Override
public void run() {
// 线程执行代码
System.out.println("Thread running");
}
}
// 使用
Thread thread = new Thread(new MyRunnable());
thread.start();
方式3:Lambda 表达式
Thread thread = new Thread(() -> {
System.out.println("Thread running");
});
thread.start();
线程状态
线程状态转换
NEW → RUNNABLE → BLOCKED → WAITING → TIMED_WAITING → TERMINATED
状态说明
// NEW:新建状态
Thread thread = new Thread();
// RUNNABLE:可运行状态
thread.start();
// BLOCKED:阻塞状态(等待锁)
synchronized (lock) {
// 其他线程等待锁
}
// WAITING:等待状态
thread.wait();
LockSupport.park();
// TIMED_WAITING:超时等待
Thread.sleep(1000);
thread.wait(1000);
// TERMINATED:终止状态
// 线程执行完毕
线程同步
synchronized
// 同步方法
public synchronized void method() {
// 临界区代码
}
// 同步代码块
public void method() {
synchronized (this) {
// 临界区代码
}
}
// 同步静态方法
public static synchronized void staticMethod() {
// 临界区代码
}
Lock
// ReentrantLock
private Lock lock = new ReentrantLock();
public void method() {
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
}
// ReadWriteLock
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
private Lock readLock = readWriteLock.readLock();
private Lock writeLock = readWriteLock.writeLock();
volatile
// volatile:保证可见性,不保证原子性
private volatile boolean flag = false;
// 适用场景
// 1. 状态标志
// 2. 双重检查锁定
线程通信
wait/notify
// wait:等待
synchronized (lock) {
while (!condition) {
lock.wait(); // 释放锁,等待通知
}
}
// notify:通知
synchronized (lock) {
condition = true;
lock.notify(); // 唤醒一个等待线程
// lock.notifyAll(); // 唤醒所有等待线程
}
CountDownLatch
// CountDownLatch:等待多个线程完成
CountDownLatch latch = new CountDownLatch(3);
// 线程中
latch.countDown();
// 主线程等待
latch.await();
CyclicBarrier
// CyclicBarrier:多个线程等待到齐
CyclicBarrier barrier = new CyclicBarrier(3);
// 线程中
barrier.await();
线程安全
线程安全问题
// ❌ 问题:非线程安全
private int count = 0;
public void increment() {
count++; // 非原子操作
}
// ✅ 解决:使用同步
private int count = 0;
public synchronized void increment() {
count++;
}
线程安全集合
// ConcurrentHashMap:线程安全的 HashMap
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
// CopyOnWriteArrayList:线程安全的 ArrayList
CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
// BlockingQueue:阻塞队列
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
线程基础最佳实践
1. 避免在 UI 线程执行耗时操作
// ❌ 错误
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
loadDataFromNetwork(); // 阻塞 UI 线程
}
// ✅ 正确
new Thread(() -> {
loadDataFromNetwork();
runOnUiThread(() -> {
updateUI();
});
}).start();
2. 使用线程池
// 使用线程池管理线程
ExecutorService executor = Executors.newCachedThreadPool();
executor.execute(() -> {
// 执行任务
});
3. 及时释放资源
@Override
protected void onDestroy() {
super.onDestroy();
// 停止线程
if (thread != null) {
thread.interrupt();
}
}
面试常见问题
Q1: 线程和进程的区别?
答案:
- 进程:程序执行的基本单位,有独立内存空间
- 线程:CPU 调度的基本单位,共享进程内存空间
Q2: 如何创建线程?
答案:
- 继承 Thread
- 实现 Runnable
- 使用 Lambda 表达式
Q3: 线程状态?
答案: NEW → RUNNABLE → BLOCKED → WAITING → TIMED_WAITING → TERMINATED
Q4: 线程同步方式?
答案:
- synchronized
- Lock
- volatile
- 原子类
Q5: wait 和 sleep 的区别?
答案:
- wait:释放锁,需要 notify 唤醒
- sleep:不释放锁,时间到自动唤醒
最后更新:2024年