Java并发:从经典线程到协程与async/await
\n\nJava是一门从诞生之初就支持多任务同时运行的语言。但世界在不断进步。今天我们来聊聊Java并发——从传统的线程(Thread)到虚拟线程(Project Loom中的协程),再到基于async/await的异步方法(以CompletableFuture为例)。
\n\n如果你正在使用Java,希望你的服务器在高负载下不会“卡顿”,同时代码保持可读性——那么这篇文章就是为你准备的。开始吧!
\n\n为什么并发对现代Java开发者如此重要?
\n\n想象一下,你的网站每秒处理10,000个请求。如果每个请求都顺序执行,用户将等待到天荒地老。Java并发允许你“同时”执行多个任务,高效利用CPU资源。
\n\n现代应用不仅仅是CRUD。它们涉及微服务、数据流处理、WebSocket、实时分析。如果不理解Java多线程,你可能会写出要么因OutOfMemoryError崩溃,要么运行缓慢如蜗牛的代码。
\n\n第一层:经典线程(Thread)——基础
\n\nJava中的线程是并行执行代码的最底层抽象。每个线程都是操作系统内部的一个独立“轻量级”进程。
\n\n下面是一个创建线程的简单示例:
\n\npublic class ThreadExample {\n public static void main(String[] args) {\n Thread thread = new Thread(() -> {\n for (int i = 0; i < 5; i++) {\n System.out.println("来自线程的问候:" + i);\n try {\n Thread.sleep(1000);\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n }\n });\n thread.start();\n System.out.println("主线程继续工作");\n }\n}\n\n优点:
\n- \n
- 创建简单——new Thread(() -> { ... }).start(); \n
- 直接控制生命周期。 \n
缺点:
\n- \n
- 创建线程开销大(栈内存、上下文切换的额外成本)。 \n
- 数量有限:10,000个线程可能拖垮你的JVM。 \n
- 同步复杂:死锁、竞态条件。 \n
经典方法适用于小任务,但不适合高负载应用。这时Java虚拟线程就派上了用场。
\n\n第二层:虚拟线程(Project Loom)——Java中的协程
\n\n如果你听说过Go语言中的协程,那么Java虚拟线程几乎与之相同。它们随Java 21(Project Loom)引入,彻底改变了游戏规则。
\n\n虚拟线程是由JVM而非操作系统管理的“轻量级”线程。你可以创建数百万个,它们只消耗极少的内存。
\n\n创建虚拟线程的示例:
\n\npublic class VirtualThreadExample {\n public static void main(String[] args) throws InterruptedException {\n // 创建100,000个虚拟线程\n var threads = new Thread[100_000];\n for (int i = 0; i < threads.length; i++) {\n threads[i] = Thread.startVirtualThread(() -> {\n // 模拟阻塞I/O操作\n try {\n Thread.sleep(1000);\n } catch (InterruptedException e) {\n Thread.currentThread().interrupt();\n }\n });\n }\n for (Thread t : threads) {\n t.join();\n }\n System.out.println("所有虚拟线程已完成!");\n }\n}\n\n太棒了,不是吗?