Форум программистов, компьютерный форум, киберфорум
Java SE (J2SE)
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.75/4: Рейтинг темы: голосов - 4, средняя оценка - 4.75
2 / 1 / 1
Регистрация: 24.04.2010
Сообщений: 76

Чтение файла через ForkJoinPool

14.03.2019, 11:02. Показов 902. Ответов 1

Студворк — интернет-сервис помощи студентам
Есть большой файл, около 500К строк. В каждой строке файла есть идентификатор , характеризующий одну из 50 таблиц (энтити, класс). Мне надо как-то очень оптимально пробежаться по этому файлу, достать каждую строку и кинуть её в уже написанный обрабтчик. Мне настоятельно рекомендовали использовать ForkJoinPool. Пока не получается то, что хочется.

Запуск в методе разбора файла
Java
1
2
3
4
5
6
    public void parseFile() {
        ForkJoinPool pool = new ForkJoinPool(4);
        FileParserProcessor fileParser = new FileParserProcessor("MyBigFile.txt", 24);
        pool.invoke(fileParser);
        pool.shutdown();
    }
Моя неправильная реализация:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class FileParserProcessor extends RecursiveAction {
    private long workLoad = 0;
    private String path;
 
    public FileParserProcessor(String path, long workLoad) {
        this.workLoad = workLoad;
        this.path = path;
    }
 
 
    @Override
    protected void compute() {
        //if work is above threshold, break tasks up into smaller tasks
        if(this.workLoad > 16) {
 
            List<FileParserProcessor> subtasks =
                    new ArrayList<FileParserProcessor>(createSubtasks());
 
            for(RecursiveAction subtask : subtasks){
                subtask.fork();
            }
 
        } else {
            try (BufferedReader br = new BufferedReader(
                    // TODO: to make file upload via interface
                    new FileReader(path)
            )) {
                String line;
                while ((line = br.readLine()) != null) {
                    System.out.println(line);
                }
            } catch (FileNotFoundException e) {
                throw new RuntimeException("An error occurred: file not found", e);
            } catch (IOException e) {
                throw new RuntimeException("An error occurred while parsing file", e);
            }
        }
    }
 
    private List<FileParserProcessor> createSubtasks() {
        List<FileParserProcessor> subtasks =
                new ArrayList<FileParserProcessor>();
 
        FileParserProcessor subtask1 = new FileParserProcessor(path, this.workLoad / 2);
        FileParserProcessor subtask2 = new FileParserProcessor(path, this.workLoad / 2);
 
        subtasks.add(subtask1);
        subtasks.add(subtask2);
 
        return subtasks;
    }
}
Добавлено через 6 минут
При этом я нашёл вариант решения через ExecutorService. Плохо только то, что нужно знать количество строк, чтобы задать capacity в BlockingQueue. Подразумевается, что впоследствии файлы будут загружаться пользователем, поэтому количество строк может быть каким угодно.

Найденное решение через ExecutorService:
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
    public void parseFile() {
        final int threadCount = Runtime.getRuntime().availableProcessors();
        BlockingQueue<String> queue = new ArrayBlockingQueue<String>(2000000);
        // create thread pool with given size
        ExecutorService service = Executors.newFixedThreadPool(threadCount);
        for (int i = 0; i < (threadCount - 1); i++) {
                service.submit(new CPUTask(queue));
        }
        // Wait til FileTask completes
        try {
            service.submit(new FileTask(queue)).get();
        } catch (InterruptedException | ExecutionException e) {
            throw new RuntimeException("An error .......................................", e);
        }
        service.shutdownNow();  // interrupt CPUTasks
        // Wait til CPUTasks terminate
        try {
            service.awaitTermination(5, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            throw new RuntimeException("An error occurred when terminate parsing process by timeout", e);
        }
    }
 
    class CPUTask implements Runnable {
        private final BlockingQueue<String> queue;
 
        public CPUTask(BlockingQueue<String> queue) {
            this.queue = queue;
        }
 
        public void run() {
            String line;
 
            while (true) {
                try {
                    // block if the queue is empty
                    line = queue.take();
 
                    System.out.println(line);
 
                    // do things with line
                } catch (InterruptedException ex) {
                    break; // FileTask has completed
                }
            }
        }
    }
 
    class FileTask implements Runnable {
        private final BlockingQueue<String> queue;
 
        public FileTask(BlockingQueue<String> queue) {
            this.queue = queue;
        }
 
        public void run() {
            try (BufferedReader br = new BufferedReader(
                    // TODO: to make file upload via interface
                    new FileReader("MyVeryBigFile.txt")
            )) {
                String line;
                while ((line = br.readLine()) != null) {
                    // block if the queue is full
                    queue.put(line);
                }
            } catch (FileNotFoundException e) {
                throw new RuntimeException("An error occurred: file not found", e);
            } catch (IOException | InterruptedException e) {
                throw new RuntimeException("An error occurred while parsing file", e);
            }
        }
    }
Добавлено через 22 минуты
А через параллельные стримы будет оптимально? вот так, например:

Java
1
2
3
4
5
6
7
8
9
    public void parseFile() {
        try {
            Stream<String> lines = Files.lines(Paths.get("MyBigFile.txt"));
            lines.parallel()
                    .forEach(System.out::println);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
14.03.2019, 11:02
Ответы с готовыми решениями:

Как заменить чтение строки из консоли на чтение текстового файла?
основное задание: найти частоту суффикса (например, &quot;ing&quot;) в текстовом документе. в прикреплённом коде текст вводится прямо в консоль,...

Запись файла через одно приложение, а чтение через другое
Есть 2 консольные программы. 1-я пишет в файл &quot;z&quot; текст, 2-я читает с файла &quot;z&quot; этот текст и работает с ним. Подскажите как...

Чтение файла через while
Делаю лабу, но не знаю какое условие писать в while ибо обычное !feof(file) не подходит, выдаёт ошибку. void Read_Data_Base(Data_base ...

1
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
14.03.2019, 11:40
Цитата Сообщение от maksimka2112 Посмотреть сообщение
А через параллельные стримы будет оптимально? вот так, например:
ты же знаешь, что можешь запустить код и посмотреть? Скорее всего читать один файл в несколько потоков смысла нет
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.03.2019, 11:40
Помогаю со студенческими работами здесь

Чтение из файла через класс
Здравствуйте! У меня нубский вопрос... Имеется класс формы (Form1) с обработчиком события button1_Click public partial class...

Чтение из файла через fscanf
Файл такого содержания petrov 4305 5.000000 sidorov 4306 4.000000 пытаюсь записать в массив через функцию while (((fscanf(data,...

Чтение файла через API
Доброго времени суток! Создаю здесь тему повторно т.к в разделе Win Api никто не читает изменил код для удобства. Помогите разобраться...

Чтение xml файла через for
Здравствуйте, как сделать так, чтобы progressbar работал по мере добавления, знаю, как сделать через for, но не знаю, как двигать...

Чтение файла через fstream
прочитать из файла матрицу и записать в новый файл её минимальный элемент в первой строке задана размерность матрицы файл: 10 8 ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Отображение реквизитов в документе по условию и контроль их заполнения
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеСпецтехники", разработанного в конфигурации КА2. Данный документ берёт данные из другого нетипового документа. . .
Фото всей Земли с борта корабля Orion миссии Artemis II
kumehtar 04.04.2026
Это первое подобное фото сделанное человеком за 50 лет. Снимок называют новым вариантом легендарной фотографии «The Blue Marble» 1972 года, сделанной с борта корабля «Аполлон-17». Новое фото. . .
Вывод диалогового окна перед закрытием, если документ не проведён
Maks 04.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать программный контроль на предмет проведения документа. . .
Программный контроль заполнения реквизита табличной части документа
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: реализовать контроль заполнения реквизита "ПричинаСписания". . .
wmic не является внутренней или внешней командой
Maks 02.04.2026
Решение: DISM / Online / Add-Capability / CapabilityName:WMIC~~~~ Отсюда: https:/ / winitpro. ru/ index. php/ 2025/ 02/ 14/ komanda-wmic-ne-naydena/
Программная установка даты и запрет ее изменения
Maks 02.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "СписаниеМатериалов", разработанного в конфигурации КА2. Задача: при создании документов установить период списания автоматически. . .
Вывод данных в справочнике через динамический список
Maks 01.04.2026
Реализация из решения ниже выполнена на примере нетипового справочника "Спецтехника" разработанного в конфигурации КА2. Задача: вывести данные из ТЧ нетипового документа. . .
Программное заполнения текстового поля в реквизите формы документа
Maks 01.04.2026
Алгоритм из решения ниже реализован на нетиповом документе "ВыдачаОборудованияНаСпецтехнику" разработанного в конфигурации КА2, в дополнении к предыдущему решению. На форме документа создается. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru