面试题:【多线程问题,三个线程A,B,C;C线程依赖B线程的结果执行,怎么控制】

发布于:2025-08-15 ⋅ 阅读:(17) ⋅ 点赞:(0)

在 Java 中,若需要控制线程间的依赖关系(如 C 线程依赖 B 线程的结果),可以通过以下几种方式实现:

方案 1:使用 CountDownLatch
CountDownLatch 是一个同步工具类,允许一个或多个线程等待其他线程完成操作。
实现步骤:

  1. 定义一个 CountDownLatch,初始计数设为 1(表示 B 线程完成后需要触发一次通知)。
  2. B 线程执行完成后,调用 countDown() 方法减少计数。
  3. C 线程启动时调用 await(),阻塞直到计数变为 0(即 B 线程完成)。
    示例代码:
import java.util.concurrent.CountDownLatch;

public class ThreadDependentExample {
    public static void main(String[] args) throws InterruptedException {
        CountDownLatch latch = new CountDownLatch(1);

        // 启动线程 B,完成后触发 latch.countDown()
        Thread bThread = new Thread(() -> {
            System.out.println("B 线程开始执行");
            // 模拟 B 的处理逻辑
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("B 线程完成");
            latch.countDown(); // 通知 C 可以执行
        });

        // 启动线程 C,等待 B 完成后执行
        Thread cThread = new Thread(() -> {
            try {
                System.out.println("C 线程等待 B 完成");
                latch.await(); // 阻塞直到 B 完成
                System.out.println("C 线程开始执行,B 已完成");
                // C 的处理逻辑
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("C 线程被中断");
            }
        });

        // 启动线程 A(独立执行)
        Thread aThread = new Thread(() -> {
            System.out.println("A 线程开始执行");
            try { Thread.sleep(500); } catch (InterruptedException e) {}
            System.out.println("A 线程完成");
        });

        // 启动所有线程
        aThread.start();
        bThread.start();
        cThread.start();
    }
}

方案 2:使用 CompletableFuture
CompletableFuture 是 Java 8 引入的高级异步编程工具,支持链式依赖关系。
实现步骤:

  1. 将 B 的任务包装为 CompletableFuture。
  2. 通过 thenRun 或 thenApply 方法,将 C 的任务绑定到 B 的完成后执行。
  3. 线程 A 可独立运行(通过 runAsync 并行执行)。
    示例代码:
import java.util.concurrent.CompletableFuture;

public class CompletableFutureExample {
    public static void main(String[] args) {
        // 线程 B 的任务
        CompletableFuture<Void> bFuture = CompletableFuture.runAsync(() -> {
            System.out.println("B 线程开始执行");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("B 线程完成");
        });

        // 线程 C 的任务绑定在 B 完成后执行
        bFuture.thenRun(() -> {
            System.out.println("C 线程开始执行,B 已完成");
            // C 的处理逻辑
        });

        // 线程 A 的任务独立运行
        CompletableFuture<Void> aFuture = CompletableFuture.runAsync(() -> {
            System.out.println("A 线程开始执行");
            try { Thread.sleep(500); } catch (InterruptedException e) {}
            System.out.println("A 线程完成");
        });

        // 等待所有任务完成(可选)
        try {
            CompletableFuture.allOf(aFuture, bFuture).get();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

方案 3:使用 Thread.join()
Thread.join() 方法可以让当前线程等待另一个线程执行完毕。
实现步骤:

  1. 启动线程 B 和 A。
  2. 在 C 线程的 run 方法中调用 bThread.join(),确保 B 完成后再执行 C。
    示例代码:
public class ThreadJoinExample {
    public static void main(String[] args) {
        // 启动线程 B
        Thread bThread = new Thread(() -> {
            System.out.println("B 线程开始执行");
            try { Thread.sleep(1000); } catch (InterruptedException e) {}
            System.out.println("B 线程完成");
        });

        // 启动线程 C,需等待 B 完成
        Thread cThread = new Thread(() -> {
            try {
                System.out.println("C 线程等待 B 完成");
                bThread.join(); // 等待 B 线程完成
                System.out.println("C 线程开始执行,B 已完成");
                // C 的处理逻辑
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
                System.out.println("C 线程被中断");
            }
        });

        // 启动线程 A(独立执行)
        Thread aThread = new Thread(() -> {
            System.out.println("A 线程开始执行");
            try { Thread.sleep(500); } catch (InterruptedException e) {}
            System.out.println("A 线程完成");
        });

        // 启动所有线程
        aThread.start();
        bThread.start();
        cThread.start();
    }
}

关键注意事项

  1. 线程安全:若 C 需要使用 B 的结果(如共享数据),需确保数据操作线程安全(如通过 volatile、锁或原子类)。
  2. 异常处理:确保线程执行过程中捕获异常,避免程序崩溃。
  3. 资源释放:及时关闭线程池或释放资源,避免内存泄漏。
  4. 性能调优:若任务频繁执行,优先选择 CompletableFuture 或线程池优化性能。

方案对比
| 方法 | 适用场景 | 优点 | 缺点 |
| CountDownLatch | 需要等待多个线程完成后再执行后续任务 | 简单易用,支持多个依赖项 | 需手动管理计数,线程间耦合较紧 |
| CompletableFuture | 复杂异步任务链,需要链式依赖、结果传递 | 高内聚、可组合,支持异常处理和超时 | 学习成本较高,API 较复杂 |
| Thread.join() | 仅需要等待一个线程完成,代码简洁 | 代码简洁,直接调用 | 只能等待单个线程,无法扩展到多个依赖项 |

根据需求选择最合适的方法:
• 若需要链式异步任务,优先使用 CompletableFuture。
• 若需要简单依赖关系,可选 CountDownLatch 或 Thread.join()。


网站公告

今日签到

点亮在社区的每一天
去签到