在现代软件开发中,多线程编程是提升应用性能、实现并发处理和响应式编程的重要技术。Java 作为一门从语言层级支持多线程的编程语言,在 JDK 中提供了完备的并发 API,包括 Thread、Runnable、ExecutorService、synchronized、Lock、Future、Callable、并发集合、原子变量、Fork/Join 框架等。
本篇文章将从 Java 多线程的基础概念入手,逐步深入到线程生命周期、线程通信、线程池、并发工具类的使用,结合实战项目构建一个线程池调度的爬虫工具,以图文并茂、代码为主线的形式,帮助开发者系统掌握 Java 并发编程。
线程是程序执行的最小单位。每个 Java 程序默认启动时至少包含一个主线程(main),可以通过创建新线程来并发执行任务。
项目 | 进程 | 线程 |
|---|---|---|
定义 | 独立运行的程序实体 | 进程内的最小执行单元 |
内存空间 | 独立 | 共享(堆) |
通信方式 | 复杂(IPC) | 简单(共享变量) |
开销 | 大 | 小 |
java复制编辑class MyThread extends Thread {
@Override
public void run() {
System.out.println("线程运行:" + Thread.currentThread().getName());
}
}
new MyThread().start();java复制编辑Runnable task = () -> System.out.println("Runnable 运行:" + Thread.currentThread().getName());
new Thread(task).start();java复制编辑Callable<String> callable = () -> "任务结果";
ExecutorService pool = Executors.newSingleThreadExecutor();
Future<String> future = pool.submit(callable);
System.out.println("结果:" + future.get());java复制编辑int count = 0;
for (int i = 0; i < 1000; i++) {
new Thread(() -> count++).start();
}结果并非 1000,因为多个线程同时写入,发生竞态条件。
java复制编辑synchronized(this) {
count++;
}或使用:
java复制编辑public synchronized void increment() {
count++;
}java复制编辑ReentrantLock lock = new ReentrantLock();
lock.lock();
try {
count++;
} finally {
lock.unlock();
}java复制编辑synchronized(obj) {
while (!condition) {
obj.wait();
}
// 满足条件继续
}调用 notify() 唤醒等待线程:
java复制编辑synchronized(obj) {
obj.notify();
}java复制编辑BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);生产者线程:
java复制编辑queue.put("任务");消费者线程:
java复制编辑String task = queue.take();java复制编辑ExecutorService executor = Executors.newFixedThreadPool(5);
executor.execute(() -> System.out.println("线程池任务"));方法 | 说明 |
|---|---|
newFixedThreadPool(n) | 固定线程数 |
newCachedThreadPool() | 缓存线程池 |
newSingleThreadExecutor() | 单线程池 |
newScheduledThreadPool() | 定时任务线程池 |
java复制编辑ThreadPoolExecutor pool = new ThreadPoolExecutor(
4, 10,
60, TimeUnit.SECONDS,
new LinkedBlockingQueue<>(100),
new ThreadPoolExecutor.AbortPolicy()
);等待多个线程完成再继续:
java复制编辑CountDownLatch latch = new CountDownLatch(3);
new Thread(() -> {
// 任务
latch.countDown();
}).start();
latch.await(); // 等待全部完成多个线程相互等待:
java复制编辑CyclicBarrier barrier = new CyclicBarrier(3, () -> System.out.println("全部到达"));
for (int i = 0; i < 3; i++) {
new Thread(() -> {
barrier.await(); // 等待其他线程
}).start();
}控制线程数量(限流):
java复制编辑Semaphore semaphore = new Semaphore(2); // 同时最多 2 个线程
semaphore.acquire();
try {
// 执行任务
} finally {
semaphore.release();
}css复制编辑爬虫线程池项目/
├── Main.java
├── CrawlerTask.java
├── ResultSaver.javajava复制编辑public class CrawlerTask implements Runnable {
private final String url;
public CrawlerTask(String url) {
this.url = url;
}
@Override
public void run() {
try {
Document doc = Jsoup.connect(url).get();
String title = doc.title();
ResultSaver.save(url, title);
} catch (IOException e) {
System.err.println("抓取失败:" + url);
}
}
}java复制编辑public class ResultSaver {
private static final Map<String, String> results = new ConcurrentHashMap<>();
public static void save(String url, String title) {
results.put(url, title);
System.out.println(url + " -> " + title);
}
}java复制编辑public class Main {
public static void main(String[] args) {
ExecutorService pool = Executors.newFixedThreadPool(5);
List<String> urls = Arrays.asList(
"https://www.baidu.com",
"https://www.sina.com.cn",
"https://www.csdn.net"
);
for (String url : urls) {
pool.submit(new CrawlerTask(url));
}
pool.shutdown();
}
}运行输出:
arduino复制编辑https://www.baidu.com -> 百度一下,你就知道
https://www.csdn.net -> CSDN - 专业开发者社区
https://www.sina.com.cn -> 新浪首页本文系统讲解了 Java 多线程编程的核心知识,包括线程创建、生命周期管理、同步机制、线程池、并发控制工具、以及线程间通信。同时,通过实际项目构建了一个基于线程池的网页爬虫工具,帮助读者将理论转化为实战能力。
java.util.concurrent.atomic 原子类
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。