MST

星途 面试题库

面试题:Java中Latch在复杂并发场景下的优化使用

假设在一个大型分布式系统中,多个子任务并行执行,完成后汇总结果。但部分子任务依赖其他子任务的中间结果,使用Latch(CountDownLatch或CyclicBarrier等)来设计并实现一个解决方案,说明如何通过Latch来协调这些任务,以及在高并发场景下如何优化性能,避免死锁等问题。
33.4万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

1. 使用CountDownLatch协调任务

假设我们有多个子任务,其中一些子任务依赖其他子任务的中间结果。

import java.util.concurrent.CountDownLatch;

public class DistributedTask {

    public static void main(String[] args) {
        int totalTasks = 5;
        CountDownLatch latch = new CountDownLatch(totalTasks);

        // 定义依赖其他任务的子任务
        Runnable dependentTask = () -> {
            try {
                // 等待其他任务完成
                latch.await();
                System.out.println("Dependent task is starting after all dependencies are done.");
                // 执行依赖任务的逻辑
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        };

        // 定义其他普通子任务
        for (int i = 0; i < totalTasks; i++) {
            new Thread(() -> {
                try {
                    // 模拟任务执行
                    Thread.sleep(1000);
                    System.out.println("Task completed.");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    // 任务完成,减少计数器
                    latch.countDown();
                }
            }).start();
        }

        new Thread(dependentTask).start();
    }
}

2. 使用CyclicBarrier协调任务

import java.util.concurrent.CyclicBarrier;

public class DistributedTaskWithCyclicBarrier {

    public static void main(String[] args) {
        int totalTasks = 5;
        CyclicBarrier barrier = new CyclicBarrier(totalTasks, () -> {
            System.out.println("All tasks are at the barrier, starting dependent task.");
            // 执行依赖任务的逻辑
        });

        for (int i = 0; i < totalTasks; i++) {
            new Thread(() -> {
                try {
                    // 模拟任务执行
                    Thread.sleep(1000);
                    System.out.println("Task completed.");
                    // 到达屏障
                    barrier.await();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

3. 高并发场景下性能优化及避免死锁

  • 性能优化
    • 减少等待时间:尽量让任务执行时间缩短,比如优化算法、使用更高效的数据结构。如果任务中有I/O操作,可以考虑使用异步I/O。
    • 合理设置并行度:根据系统资源(如CPU核心数、内存等)合理设置并行执行的任务数量,避免过多任务竞争资源导致性能下降。
  • 避免死锁
    • 顺序执行:确保所有任务按照相同的顺序获取和释放资源。比如在多个任务依赖关系复杂时,给任务编号,依赖关系按编号顺序执行。
    • 超时机制:在使用await方法时设置超时时间。如latch.await(5, TimeUnit.SECONDS),如果等待超过5秒则放弃等待,避免无限期等待。
    • 资源分配图算法:在复杂依赖场景下,可以使用资源分配图算法(如死锁检测算法)来动态检测和避免死锁。定期检查系统中任务和资源的依赖关系,发现死锁隐患及时处理。