Страницы

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

вторник, 23 апреля 2019 г.

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

Как сделать чтобы один поток подсчитывал количество строк в одном файле, второй во втором и т.д.?
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); } } } }


Ответ

Статический метод 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

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

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