MST

星途 面试题库

面试题:Java递归目录深度遍历在多线程环境下的优化与并发控制

假设要在多线程环境下对目录进行深度遍历,每个线程负责一个子目录,且要保证遍历结果的正确性和高效性。请设计一个基于Java多线程的目录深度遍历方案,结合递归实现,并处理好线程同步、资源竞争等问题。请写出核心的类和方法的代码框架,并详细解释你的设计思路,包括如何使用锁机制、线程池等技术来优化整个过程。
22.0万 热度难度
编程语言Java

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 任务划分:将目录遍历任务按子目录划分,每个线程负责一个子目录的深度遍历。
  2. 线程同步:使用锁机制来处理资源竞争,防止多个线程同时访问同一资源。
  3. 线程池:利用线程池来管理线程,提高线程的复用性,减少线程创建和销毁的开销。
  4. 递归实现:在每个线程处理的子目录中,通过递归继续对其子目录进行深度遍历。

核心类和方法代码框架

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.io.File;
import java.util.ArrayList;
import java.util.List;

public class DirectoryTraversal {
    private static final int THREAD_POOL_SIZE = 10;
    private static final Lock lock = new ReentrantLock();
    private static List<String> result = new ArrayList<>();
    private static ExecutorService executorService = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

    public static void main(String[] args) {
        File rootDir = new File("/your/directory/path");
        traverseDirectory(rootDir);
        executorService.shutdown();
        while (!executorService.isTerminated()) {
            // 等待所有任务完成
        }
        for (String path : result) {
            System.out.println(path);
        }
    }

    private static void traverseDirectory(File directory) {
        if (!directory.isDirectory()) {
            return;
        }
        File[] files = directory.listFiles();
        if (files != null) {
            for (File file : files) {
                if (file.isDirectory()) {
                    executorService.submit(() -> {
                        lock.lock();
                        try {
                            traverseDirectory(file);
                        } finally {
                            lock.unlock();
                        }
                    });
                } else {
                    lock.lock();
                    try {
                        result.add(file.getAbsolutePath());
                    } finally {
                        lock.unlock();
                    }
                }
            }
        }
    }
}

代码解释

  1. 常量定义THREAD_POOL_SIZE 定义线程池大小,lock 用于线程同步,result 用于存储遍历结果。
  2. 线程池:使用 Executors.newFixedThreadPool(THREAD_POOL_SIZE) 创建固定大小的线程池。
  3. traverseDirectory 方法:递归方法,负责处理目录遍历。如果是子目录,提交新任务到线程池处理;如果是文件,则直接添加到结果列表。
  4. 锁机制:在访问共享资源(result 列表)或递归调用 traverseDirectory 方法时,使用 lock 进行加锁和解锁,保证线程安全。
  5. 主线程:在 main 方法中启动遍历任务,并等待线程池中的所有任务完成后输出结果。