Java线程详解
📌摘要
本文系统讲解了Java中线程的基础知识、线程同步机制、并发工具类、高级主题(如 Fork/Join 和 CompletableFuture)、性能优化策略以及实际项目中的应用案例。每节均配有完整的示例代码,适合初学者入门和中级开发者深入学习。
🎯一、引言
在现代多核处理器架构下,并发编程已成为高性能应用开发的核心技能之一。Java自诞生之初就内置了对线程的支持,使得开发者能够轻松地实现多线程程序。本文将系统讲解Java线程的基础知识、同步机制、并发工具类、高级主题以及最佳实践,帮助你构建稳定、高效的并发程序。
🧱二、Java线程基础
1. 什么是线程?
线程是操作系统调度的最小单位,属于进程的一部分。多个线程共享同一个进程的资源(如内存、文件句柄等),相比进程切换开销更小。
进程 vs 线程
- 进程:独立地址空间,资源隔离。
- 线程:轻量级执行单元,共享进程资源。
2. 创建线程的方法
方法一:继承 Thread 类
class MyThread extends Thread {
public void run() {
System.out.println("Hello from thread: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start(); // 启动线程
}
}
方法二:实现 Runnable 接口(推荐)
class MyRunnable implements Runnable {
public void run() {
System.out.println("Running in thread: " + Thread.currentThread().getName());
}
}
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new MyRunnable(), "MyWorker");
t.start();
}
}
方法三:使用 ExecutorService(推荐用于生产环境)
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Main {
public static void main(String[] args) {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(() -> System.out.println("Task executed by thread pool"));
executor.shutdown();
}
}
3. 线程生命周期
Java 中线程有六种状态:
| 状态 | 描述 |
|---|---|
| NEW | 刚创建未启动 |
| RUNNABLE | 正在运行或等待CPU时间片 |
| BLOCKED | 等待进入同步方法/代码块 |
| WAITING | 无限期等待其他线程唤醒 |
| TIMED_WAITING | 定时等待 |
| TERMINATED | 线程执行完毕 |
4. 线程优先级
Java中线程优先级范围是1~10,默认值为5。
Thread t1 = new Thread(() -> System.out.println("T1"));
Thread t2 = new Thread(() -> System.out.println("T2"));
t1.setPriority(Thread.MIN_PRIORITY); // 1
t2.setPriority(Thread.MAX_PRIORITY); // 10
t1.start();
t2.start();
⚠️ 注意:线程优先级只是提示,并不保证高优先级一定先执行。
🔐三、线程同步与通信
1. 线程安全问题
当多个线程同时访问共享资源时,可能会出现数据不一致的问题。
class Counter {
int count = 0;
void increment() {
count++;
}
}
多线程调用
increment()可能导致结果错误。
2. 同步机制
使用 synchronized 关键字
class Counter {
private int count = 0;
synchronized void increment() {
count++;
}
int getCount() {
return count;
}
}
显式锁 ReentrantLock
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
class Counter {
private final Lock lock = new ReentrantLock();
private int count = 0;
void increment() {
lock.lock();
try {
count++;
} finally {
lock.unlock();
}
}
}
3. 线程间通信
使用 wait() / notify() 实现线程协作。
class SharedResource {
boolean isAvailable = false;
synchronized void produce() throws InterruptedException {
while (isAvailable) wait();
isAvailable = true;
System.out.println("Produced");
notify();
}
synchronized void consume() throws InterruptedException {
while (!isAvailable) wait();
isAvailable = false;
System.out.println("Consumed");
notify();
}
}
🧰四、并发工具类
1. CountDownLatch
适用于主线程等待多个子线程完成任务后继续执行。
import java.util.concurrent.CountDownLatch;
public class LatchExample {
public static void main(String[] args) throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " working...");
latch.countDown();
}).start();
}
latch.await(); // 阻塞直到计数归零
System.out.println("All threads completed.");
}
}
2. CyclicBarrier
多个线程互相等待,到达屏障点后再一起继续执行。
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
public class BarrierExample {
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("All arrived!"));
for (int i = 0; i < 3; i++) {
new Thread(() -> {
System.out.println(Thread.currentThread().getName() + " arrived.");
try {
barrier.await();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}).start();
}
}
}
3. Semaphore
控制同时访问的线程数量。
import java.util.concurrent.Semaphore;
public class SemaphoreExample {
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(2); // 允许两个线程并发
for (int i = 0; i < 5; i++) {
new Thread(() -> {
try {
semaphore.acquire();
System.out.println(Thread.currentThread().getName() + " is using resource.");
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
semaphore.release();
}
}).start();
}
}
}
4. Exchanger
用于两个线程之间交换数据。
import java.util.concurrent.Exchanger;
public class ExchangerExample {
public static void main(String[] args) {
Exchanger<String> exchanger = new Exchanger<>();
new Thread(() -> {
String data = "Data from Thread 1";
try {
String result = exchanger.exchange(data);
System.out.println("Received: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T1").start();
new Thread(() -> {
String data = "Data from Thread 2";
try {
String result = exchanger.exchange(data);
System.out.println("Received: " + result);
} catch (InterruptedException e) {
e.printStackTrace();
}
}, "T2").start();
}
}
🚀五、高级主题
1. Fork/Join 框架
适用于分治型任务,如排序、搜索等。
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;
class SumTask extends RecursiveTask<Integer> {
private final int[] array;
private final int start, end;
SumTask(int[] array, int start, int end) {
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected Integer compute() {
if (end - start <= 2) {
int sum = 0;
for (int i = start; i < end; i++) {
sum += array[i];
}
return sum;
}
int mid = (start + end) / 2;
SumTask left = new SumTask(array, start, mid);
SumTask right = new SumTask(array, mid, end);
left.fork();
right.fork();
return left.join() + right.join();
}
}
public class ForkJoinExample {
public static void main(String[] args) {
int[] array = {1, 2, 3, 4, 5, 6, 7, 8};
ForkJoinPool pool = new ForkJoinPool();
int result = pool.invoke(new SumTask(array, 0, array.length));
System.out.println("Total sum: " + result);
}
}
2. CompletableFuture
Java 8 引入的异步编程新方式。
import java.util.concurrent.CompletableFuture;
public class FutureExample {
public static void main(String[] args) {
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
System.out.println("Task running in async thread: " + Thread.currentThread().getName());
});
future.join(); // 等待任务完成
}
}
3. 虚拟线程(Java 19+)
轻量级线程,极大提升并发能力。
// JDK 21 示例
public class VirtualThreadExample {
public static void main(String[] args) throws Exception {
Thread.ofVirtual().start(() -> {
System.out.println("Running in virtual thread: " + Thread.currentThread());
});
}
}
⚙️六、性能优化与最佳实践
1. 线程池的选择与配置
ExecutorService fixedPool = Executors.newFixedThreadPool(4); // CPU密集型
ExecutorService cachedPool = Executors.newCachedThreadPool(); // IO密集型
ExecutorService singlePool = Executors.newSingleThreadExecutor(); // 单线程顺序执行
2. 减少上下文切换开销
- 控制线程数量,避免过多线程竞争资源。
- 使用批处理减少频繁创建线程。
3. 错误处理与日志记录
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
System.err.println("Uncaught exception in thread " + t.getName() + ": " + e.getMessage());
});
🧪七、案例研究
1. 实际项目中的线程应用
以电商系统为例,订单创建后需要异步更新库存、发送短信、写入日志等操作,可使用线程池进行解耦:
ExecutorService orderExecutor = Executors.newFixedThreadPool(4);
orderExecutor.submit(() -> updateInventory(order));
orderExecutor.submit(() -> sendNotification(user));
orderExecutor.submit(() -> logOrder(order));
2. 性能测试与分析
使用 JMH 进行基准测试,比较同步与异步处理性能差异。
@Benchmark
public void testSyncProcessing() {
processOrdersSynchronously();
}
@Benchmark
public void testAsyncProcessing() {
processOrdersAsynchronously();
}
🧠八、总结
Java线程是构建高性能、响应式系统的关键技术。通过掌握线程的生命周期、同步机制、并发工具类和高级特性,你可以写出更加高效、稳定的并发程序。随着虚拟线程、结构化并发等新技术的引入,Java在并发编程领域的优势将进一步增强。
-
如果你在学习过程中遇到任何疑问,欢迎在评论区留言交流!
-
👍 如果你觉得这篇文章对你有帮助,别忘了点赞、收藏、转发哦!

浙公网安备 33010602011771号