You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Kotlin中(1..100).map{launch{...}}.forEach{it.join()}可并行执行?

Why Kotlin's Coroutine Code Runs in Parallel, Unlike the Equivalent Java Thread Approach

Great question! This is a perfect example of how Kotlin's coroutine model differs fundamentally from Java's raw thread handling—let's break down exactly why the behaviors are so different.

First, Let's Confirm the Java Scenario (Serial Execution)

You’re spot-on about the Java case. If you wrote code that starts a thread and immediately calls join() like this:

for (int i = 1; i <= 100; i++) {
    Thread thread = new Thread(() -> {
        System.out.println("Hello from " + Thread.currentThread().getName());
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    });
    thread.start();
    thread.join(); // Blocks the main thread right away
}

This runs one thread at a time because Thread.join() is a blocking call. When you invoke it, the main thread stops entirely and waits for that single worker thread to finish its work. It can’t start the next thread until the current one is done—so no parallelism here.

Why the Kotlin Code Achieves Parallelism

Your Kotlin code uses coroutines, not raw threads, and that’s where the key differences lie:

1. launch Creates Lightweight Coroutines, Not Threads

When you call launch { ... }, you’re not spawning a new thread immediately. Instead, you’re creating a coroutine—a lightweight, suspendable task managed by a coroutine dispatcher (by default, Dispatchers.Default, which uses a shared thread pool). Multiple coroutines can run on the same thread, and the dispatcher handles switching between them efficiently without the overhead of thread creation.

2. Job.join() Suspends the Coroutine, Not the Thread

The join() method you’re calling on the Job returned by launch is nothing like Thread.join(). It’s a suspending function:

  • When you call join(), only the current coroutine (the one running the forEach loop) pauses its execution.
  • The underlying thread that was running this coroutine is now free to execute other coroutines that you’ve already launched (all 100 of them, in your case).
  • Once the target coroutine finishes its work (prints the message and waits 100ms), the paused loop coroutine resumes and moves on to the next join().

3. Let’s Walk Through the Execution Flow

Here’s what happens step-by-step in your Kotlin code:

  1. Launch all coroutines first: (1..100).map { launch { ... } } spins up all 100 coroutines almost instantly. The dispatcher adds them to its queue and starts executing them on available threads in the pool.
  2. Wait for each coroutine (without blocking): The forEach { it.join() } loop iterates over each Job:
    • For the first job, join() suspends the loop coroutine. The thread it was using can now run other waiting coroutines.
    • As each coroutine finishes, the corresponding join() call resumes, and the loop moves to the next job.
  3. Parallel execution: Since all coroutines are launched up front and the loop only suspends (not blocks), all 100 coroutines run in parallel across the thread pool.

Key Takeaway

The core distinction is:

  • Java’s Thread.join() blocks the entire thread, halting all work on that thread until the target thread completes.
  • Kotlin’s coroutine Job.join() suspends only the current coroutine, allowing the thread to handle other tasks while waiting.

内容的提问来源于stack exchange,提问作者neuron

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:22:42