现代应用的性能越来越依赖并发编程。无论是 Web 服务的高并发处理,还是桌面软件的任务解耦,Java 的多线程编程能力都是不可或缺的核心技能。
Java 原生提供了强大的并发支持,从基础的 Thread 到高级的线程池、并发集合、原子类等,开发者可以高效、安全地构建多线程应用。
本篇文章将通过基础概念、核心 API、实战项目三个阶段深入讲解 Java 多线程编程,帮助你从入门到应用。
线程是进程中的最小执行单元。一个 Java 程序(进程)中可以同时运行多个线程,每个线程执行不同的任务。
java复制编辑public class MyThread extends Thread {
public void run() {
System.out.println("Hello from thread: " + Thread.currentThread().getName());
}
}
使用方式:
java复制编辑MyThread t1 = new MyThread();
t1.start();
📌 注意:不要调用 run()
,而应调用 start()
来启动线程。
java复制编辑public class MyRunnable implements Runnable {
public void run() {
System.out.println("Runnable is running: " + Thread.currentThread().getName());
}
}
使用方式:
java复制编辑Thread t = new Thread(new MyRunnable());
t.start();
java复制编辑Thread t = new Thread(() -> {
System.out.println("Lambda thread: " + Thread.currentThread().getName());
});
t.start();
css复制编辑[NEW] --> [RUNNABLE] --> [RUNNING] --> [TERMINATED]
↘
[BLOCKED]
↘
[WAITING/TIMED_WAITING]
NEW
: 创建但未启动
RUNNABLE
: 可运行状态,等待调度
BLOCKED
: 等待锁
WAITING
: 无限等待
TIMED_WAITING
: 有时间限制等待
TERMINATED
: 执行完毕或异常
操作方法 | 描述 |
---|---|
start() | 启动线程 |
sleep(ms) | 当前线程休眠 |
join() | 等待另一个线程结束 |
interrupt() | 中断线程 |
isAlive() | 判断线程是否活着 |
java复制编辑Thread t = new Thread(() -> {
try {
Thread.sleep(2000);
System.out.println("任务完成");
} catch (InterruptedException e) {
System.out.println("线程被中断");
}
});
t.start();
t.join(); // 等待它结束
多线程操作共享资源时,必须小心线程安全问题。
java复制编辑synchronized(obj) {
// 临界区
}
java复制编辑public synchronized void increment() {
count++;
}
java复制编辑ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
// 临界区
} finally {
lock.unlock();
}
java复制编辑class MessageBox {
private String message;
private boolean hasMessage = false;
public synchronized void put(String msg) throws InterruptedException {
while (hasMessage) wait();
message = msg;
hasMessage = true;
notifyAll();
}
public synchronized String take() throws InterruptedException {
while (!hasMessage) wait();
hasMessage = false;
notifyAll();
return message;
}
}
👆生产者消费者模型的基础框架。
手动创建线程有性能和管理问题,Java 推荐使用线程池(Executor)来管理线程。
java复制编辑ExecutorService pool = Executors.newFixedThreadPool(4);
pool.submit(() -> {
System.out.println("任务由线程池处理");
});
java复制编辑pool.shutdown(); // 平滑关闭
java复制编辑Callable<Integer> task = () -> {
Thread.sleep(1000);
return 42;
};
Future<Integer> result = pool.submit(task);
System.out.println("结果: " + result.get());
实现一个工具,接受多个 URL,使用线程池并发下载内容。
java复制编辑class Downloader implements Callable<String> {
private String url;
public Downloader(String url) {
this.url = url;
}
public String call() {
// 简化处理
return "下载完成:" + url;
}
}
主方法:
java复制编辑ExecutorService pool = Executors.newFixedThreadPool(5);
List<String> urls = Arrays.asList("a.com", "b.com", "c.com");
List<Future<String>> results = new ArrayList<>();
for (String url : urls) {
results.add(pool.submit(new Downloader(url)));
}
for (Future<String> f : results) {
System.out.println(f.get());
}
pool.shutdown();
📸 示例输出:
css复制编辑下载完成:a.com
下载完成:b.com
下载完成:c.com
问题 | 原因 | 解决方案 |
---|---|---|
IllegalThreadStateException | 重复调用 start() | 每个线程只能 start 一次 |
死锁 | 多线程互相等待对方释放锁 | 保持锁顺序一致,尽量少嵌套锁 |
线程池不关闭 | 未调用 shutdown | 加上 pool.shutdown() |
数据错乱 | 并发操作共享变量未同步 | 使用 synchronized 或原子类 |
Java 多线程涉及面广、应用广泛,掌握好基础后,推荐继续深入:
java.util.concurrent
高级并发包
ConcurrentHashMap
AtomicInteger
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。