Java 多线程是 Java 编程中实现并发的重要特性,允许程序同时执行多个任务。Java 多线程通过 java.lang.Thread
类和 java.util.concurrent
包实现。线程是程序执行的最小单位,多线程允许程序同时执行多个任务。
1.多线程介绍
多线程指一个进程中存在多个并发执行的线程,共享进程资源(内存、文件等),每个线程拥有独立的栈空间。优势包括:
- 提高 CPU 利用率:避免单线程阻塞导致的资源浪费
- 提升响应速度:后台任务不影响主线程响应
- 简化模型:将复杂任务拆解为独立线程
⚠️ 注意:需处理线程安全(数据竞争)和死锁问题。
2. 创建线程的三种方式
2.1 继承 Thread 类
class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程执行: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start(); // 启动线程
}
}
2.2 实现 Runnable 接口
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("线程执行: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
优势:避免单继承限制,更适合资源共享。
2.3 实现 Callable 接口(带返回值)
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "线程执行结果: " + Thread.currentThread().getName();
}
}
public class Main {
public static void main(String[] args) throws Exception {
FutureTask<String> task = new FutureTask<>(new MyCallable());
Thread thread = new Thread(task);
thread.start();
System.out.println(task.get()); // 获取返回值
}
}
3.线程的生命周期
- NEW:线程被创建但未启动。
- RUNNABLE:线程正在运行或准备运行。
- BLOCKED:线程等待监视器锁(如
synchronized
块)。 - WAITING:线程无限期等待(如
wait()
或join()
)。 - TIMED_WAITING:线程有限期等待(如
sleep(time)
)。 - TERMINATED:线程执行完毕。
4.线程同步与锁
synchronized 关键字
- 同步方法:
public synchronized void synchronizedMethod() { // 临界区代码 }
- 同步块
synchronized (lockObject) { // 临界区代码 }
ReentrantLock
java.util.concurrent.locks.ReentrantLock
提供更灵活的锁机制:
Lock lock = new ReentrantLock();
lock.lock();
try {
// 临界区代码
} finally {
lock.unlock();
}
5.线程间通信
1. 共享变量 + synchronized
(同步锁)
class SharedResource {
private int value;
private boolean available = false;
public synchronized void produce(int val) {
while (available) {
try {
wait(); // 释放锁,等待消费
} catch (InterruptedException e) { /*...*/ }
}
value = val;
available = true;
notifyAll(); // 唤醒消费线程
}
public synchronized int consume() {
while (!available) {
try {
wait(); // 等待生产
} catch (InterruptedException e) { /*...*/ }
}
available = false;
notifyAll(); // 唤醒生产线程
return value;
}
}
2. Lock
+ Condition
(更灵活)
class SharedResource {
private final Lock lock = new ReentrantLock();
private final Condition notFull = lock.newCondition();
private final Condition notEmpty = lock.newCondition();
private int value;
private boolean available = false;
public void produce(int val) {
lock.lock();
try {
while (available) {
notFull.await(); // 等待非满条件
}
value = val;
available = true;
notEmpty.signal(); // 通知非空条件
} finally {
lock.unlock();
}
}
public int consume() {
lock.lock();
try {
while (!available) {
notEmpty.await(); // 等待非空条件
}
available = false;
notFull.signal(); // 通知非满条件
return value;
} finally {
lock.unlock();
}
}
}
3. 阻塞队列 BlockingQueue
(推荐)
BlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
// 生产者
Runnable producer = () -> {
try {
queue.put(1); // 队列满时自动阻塞
} catch (InterruptedException e) { /*...*/ }
};
// 消费者
Runnable consumer = () -> {
try {
int value = queue.take(); // 队列空时自动阻塞
} catch (InterruptedException e) { /*...*/ }
};
new Thread(producer).start();
new Thread(consumer).start();
4. wait()
/ notify()
机制
-
wait()
:释放锁并进入等待状态 -
notify()
:随机唤醒一个等待线程 -
notifyAll()
:唤醒所有等待线程
必须配合
synchronized
使用,否则抛出IllegalMonitorStateException
。
6.关键概念
方法/类 | 作用说明 |
---|---|
synchronized | 保证代码块/方法的原子性访问 |
volatile | 确保变量可见性(不保证原子性) |
Thread.join() | 等待线程终止 |
Thread.yield() | 让出CPU时间(不释放锁) |
Thread.sleep() | 休眠指定时间(不释放锁) |
7.总结
-
优先用
Runnable
/Callable
:避免继承局限性 -
使用线程池:管理线程生命周期(
Executors
工具类) -
避免死锁:按固定顺序获取锁,设置超时(
tryLock()
) -
同步最小化:缩小
synchronized
范围提升性能
通过合理使用多线程,可显著提升程序性能,但务必谨慎处理线程安全与协调问题!