Java 多线程是 Java 编程中实现并发的重要特性,允许程序同时执行多个任务。Java 多线程通过 java.lang.Thread 类和 java.util.concurrent 包实现。线程是程序执行的最小单位,多线程允许程序同时执行多个任务。
1.多线程基础概念
多线程指一个进程中存在多个并发执行的线程,共享进程资源(内存、文件等),每个线程拥有独立的栈空间。优势包括:
1.1 线程与进程的区别
进程(Process):
-
操作系统资源分配的基本单位
-
拥有独立的地址空间
-
进程间通信(IPC)成本高(管道、消息队列、共享内存等)
-
创建和销毁开销大
线程(Thread):
-
CPU调度的基本单位
-
共享进程的地址空间和资源
-
线程间通信成本低(共享内存)
-
创建和销毁开销小
类比解释:
-
进程就像一家公司,拥有独立的办公空间和资源
-
线程就像公司里的员工,共享办公空间但各自独立工作
1.2 为什么需要多线程?
-
提高CPU利用率:
-
单线程在IO操作时CPU处于等待状态
-
多线程可以在一个线程等待时运行其他线程
-
-
提升吞吐量:
-
Web服务器可以同时处理多个请求
-
数据库系统可以并行执行查询
-
-
改善响应时间:
-
GUI程序主线程保持响应
-
后台线程处理耗时任务
-
-
利用多核CPU:
-
现代CPU都是多核架构
-
单线程无法充分利用硬件资源
-
1.3 多线程的挑战
-
线程安全问题:
-
竞态条件(Race Condition)
-
数据竞争(Data Race)
-
-
死锁问题:
-
多个线程互相等待对方释放锁
-
-
性能问题:
-
上下文切换开销
-
锁竞争导致的性能下降
-
-
调试困难:
-
问题难以复现
-
执行顺序不确定
-
2. Java多线程实现
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()); // 获取返回值
}
}
2.4 使用线程池(推荐方式):
ExecutorService executor = Executors.newFixedThreadPool(4);
executor.execute(() -> {
System.out.println("Task running in thread pool");
});
executor.shutdown();
3.线程的生命周期
Java线程有以下6种状态(Thread.State枚举):
-
NEW:已创建但未启动
-
RUNNABLE:正在运行或可运行
-
BLOCKED:等待获取监视器锁(synchronized)
-
WAITING:无限期等待(wait()、join())
-
TIMED_WAITING:有限期等待(sleep()、wait(timeout))
-
TERMINATED:线程已终止
状态转换:
NEW → start() → RUNNABLE
RUNNABLE → 获取锁 → BLOCKED
RUNNABLE → wait()/join() → WAITING
RUNNABLE → sleep(timeout)/wait(timeout) → TIMED_WAITING
WAITING/TIMED_WAITING → notify()/interrupt()/超时 → RUNNABLE
BLOCKED → 获取锁 → RUNNABLE
RUNNABLE → 运行结束 → TERMINATED
4.线程同步机制
synchronized 关键字
对象锁:
class Counter {
private int count = 0;
public synchronized void increment() {
count++;
}
public synchronized int getCount() {
return count;
}
}
类锁:
class StaticCounter {
private static int count = 0;
public static synchronized void increment() {
count++;
}
}
同步代码块:
public void doSomething() {
// 非同步代码
synchronized(this) {
// 同步代码块
}
}
同步方法:
public synchronized void synchronizedMethod() {
// 临界区代码
}
volatile关键字
作用:
-
保证变量的可见性
-
禁止指令重排序
-
不保证原子性
适用场景:
class VolatileExample {
private volatile boolean flag = false;
public void start() {
new Thread(() -> {
while (!flag) {
// 循环直到flag变为true
}
System.out.println("Flag is now true");
}).start();
}
public void stop() {
flag = true;
}
}
Lock接口
基本用法:
class LockExample {
private final Lock lock = new ReentrantLock();
private int count = 0;
public void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
高级特性:
// 尝试获取锁
if (lock.tryLock(1, TimeUnit.SECONDS)) {
try {
// 获取锁成功
} finally {
lock.unlock();
}
} else {
// 获取锁超时
}
// 可中断锁
lock.lockInterruptibly();
原子类
java.util.concurrent.atomic包提供原子操作类:
AtomicInteger counter = new AtomicInteger(0);
// 原子递增
counter.incrementAndGet();
// CAS操作
boolean updated = counter.compareAndSet(expect, update);
同步工具类
-
CountDownLatch:
CountDownLatch latch = new CountDownLatch(3); // 工作线程 new Thread(() -> { // 工作 latch.countDown(); }).start(); // 主线程等待 latch.await(); -
CyclicBarrier:
CyclicBarrier barrier = new CyclicBarrier(3, () -> { System.out.println("All threads reached barrier"); }); new Thread(() -> { // 工作 barrier.await(); }).start(); -
Semaphore:
Semaphore semaphore = new Semaphore(3); // 允许3个线程同时访问 semaphore.acquire(); try { // 访问资源 } finally { semaphore.release(); }
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范围提升性能
通过合理使用多线程,可显著提升程序性能,但务必谨慎处理线程安全与协调问题!
389

被折叠的 条评论
为什么被折叠?



