Страницы

Поиск по вопросам

четверг, 13 февраля 2020 г.

Многопоточная обработка файлов с использованием ExecutorService

#java #многопоточность


Как сделать чтобы один поток подсчитывал количество строк в одном файле, второй во
втором и т.д.?

public class ThreadMain {
    static ArrayList FilesFind = new ArrayList<>();

    public static void main(String[] args) {

        String mask;
        Scanner DIR_NAME = new Scanner(System.in);
        Scanner MASK_NAME = new Scanner(System.in);


        System.out.println("Введите директорию :");
        getFilesList(DIR_NAME.nextLine());

        System.out.println("Введите маску для поиска");
        mask = MASK_NAME.nextLine();

        System.out.println("Результат поиска :");

        ExecutorService executor = Executors.newFixedThreadPool(10);
        for (int i = 0; i < 10; i++) {
            Runnable worker = new ThreadPools(FilesFind, mask);
            executor.execute(worker);
        }
        executor.shutdown();
        while (!executor.isTerminated()) {
        }
        System.out.println("Потоки закончили работу");
    }

    public static void getFilesList(String nameDirectory) {
        File f = new File(nameDirectory);
        for (File str : f.listFiles()) {
            if (str.isFile()) {
                FilesFind.add(str);
            } else if (str.isDirectory()) {
                getFilesList(str.getAbsolutePath());
            }
        }
    }
}


Класс ThreadPools:

class ThreadPools implements Runnable {

    private ArrayList FilesFindThread;
    private String maskThread;
    private String search;


    ThreadPools(ArrayList FilesFind, String mask) {
        this.FilesFindThread = FilesFind;
        this.maskThread = mask;
    }

    @Override
    public void run() {
        CountStrings();
    }

    public void CountStrings() {
        for (File fill : FilesFindThread) {
            try {
                BufferedReader reader = new BufferedReader(new FileReader(fill));
                int count = 0;
                while ((search = reader.readLine()) != null) {
                    if (search.contains(maskThread) && !search.isEmpty()) {
                        count++;
                    }
                }
                reader.close();
                System.out.println(Thread.currentThread().getName() + ":" + "Name
files :" + fill.getName() + " ---- > " + count);
            } catch (java.io.IOException e) {
                System.out.println(e);
            }
        }  
    }
}

    


Ответы

Ответ 1



Статический метод Executors.newFixedThreadPool предназначен для создания пула с фиксированным числом потоков (это число вы указываете в качестве параметра конструктора). Если количество задач будет больше числа доступных потоков, то они добавляются в очередь и извлекаются из нее по мере освобождения одного из потоков. С помощью метода execute() мы запускаем выполнение определенной задачи (выполнение может начаться сразу или позже, см. выше). Поскольку нам необходимо многопоточно обработать определенное число файлов, то просто добавляем их обработку в качестве очередной задачи, за все остальное уже отвечает ExecutorService. Для завершения выполнения пула потоков используем два метода: shutdown() - сообщаем, что наш сервис больше не принимает никаких новых задач. awaitTermination() - блокирующий метод пока все задачи не будут выполнены, либо текущий поток не будет прерван, либо не будет достигнут указанный таймаут. Далее привожу пример многопоточного чтения файлов и подсчет количества строк в них. Пояснил код комментариями. Пример легко сможете адаптировать под свою задачу, добавив более сложную логику по поиску файлов на основе фильтров. Основной метод для получения исходного каталога и запуска обработки файлов: try { BufferedReader reader = new BufferedReader(new InputStreamReader(System.in)); // Считываем исходный каталог для поиска файлов. System.out.print("Введите исходную директорию для поиска файлов:"); final String directoryPath = reader.readLine(); reader.close(); File directory = new File(directoryPath); // Убедимся, что директория найдена и это реально директория, а не файл. if (directory.exists() && directory.isDirectory()) { processDirectory(directory); } else { System.out.println("Не удалось найти директорию по указанному пути."); } } catch (IOException e) { e.printStackTrace(); } Метод processDirectory(File directory) для поиска файлов и их обработки: private static void processDirectory(File directory) { // Получаем список доступных файлов в указанной директории. File[] files = directory.listFiles(); if (files == null) { System.out.println("Нет доступных файлов для обработки."); return; } else { System.out.println("Количество файлов для обработки: " + files.length); } // Непосредственно многопоточная обработка файлов. ExecutorService service = Executors.newFixedThreadPool(10); for (final File f : files) { if (!f.isFile()) { continue; } service.execute(new Runnable() { @Override public void run() { try (BufferedReader reader = new BufferedReader(new FileReader(f))) { int lines = 0; while (reader.readLine() != null) { ++lines; } System.out.println("Поток: " + Thread.currentThread().getName() + ". Файл: " + f.getName() + ". Количество строк: " + lines); } catch (IOException e) { e.printStackTrace(); } } }); } // Новые задачи более не принимаем, выполняем только оставшиеся. service.shutdown(); // Ждем завершения выполнения потоков не более 10 минут. try { service.awaitTermination(10, TimeUnit.MINUTES); } catch (InterruptedException e) { e.printStackTrace(); } } Пример выполнения данного кода: Введите исходную директорию для поиска файлов: C:\projects\FindCentroid\src\pro\parshinpn Количество файлов для обработки: 6 Поток: pool-1-thread-1. Файл: Cluster.java. Количество строк: 25 Поток: pool-1-thread-4. Файл: Point.java. Количество строк: 90 Поток: pool-1-thread-3. Файл: Graph.java. Количество строк: 120 Поток: pool-1-thread-2. Файл: Edge.java. Количество строк: 92 Поток: pool-1-thread-6. Файл: Vertex.java. Количество строк: 69 Поток: pool-1-thread-5. Файл: UnionFindStructure.java. Количество строк: 102

Комментариев нет:

Отправить комментарий