Java中的线程、协程与async/await:编写正确的并发代码

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Java并发:从经典线程到协程与async/await

\n\n

Java是一门从诞生之初就支持多任务同时运行的语言。但世界在不断进步。今天我们来聊聊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\n

Java中的线程是并行执行代码的最底层抽象。每个线程都是操作系统内部的一个独立“轻量级”进程。

\n\n

下面是一个创建线程的简单示例:

\n\n
public 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
    \n
  • 创建线程开销大(栈内存、上下文切换的额外成本)。
  • \n
  • 数量有限:10,000个线程可能拖垮你的JVM。
  • \n
  • 同步复杂:死锁、竞态条件。
  • \n
\n\n

经典方法适用于小任务,但不适合高负载应用。这时Java虚拟线程就派上了用场。

\n\n

第二层:虚拟线程(Project Loom)——Java中的协程

\n\n

如果你听说过Go语言中的协程,那么Java虚拟线程几乎与之相同。它们随Java 21(Project Loom)引入,彻底改变了游戏规则。

\n\n

虚拟线程是由JVM而非操作系统管理的“轻量级”线程。你可以创建数百万个,它们只消耗极少的内存。

\n\n

创建虚拟线程的示例:

\n\n
public 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

太棒了,不是吗?

博客

书籍推荐