2 / 1 / 1
Регистрация: 24.04.2010
Сообщений: 76
1

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

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

Author24 — интернет-сервис помощи студентам
Есть большой файл, около 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
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
14.03.2019, 11:02
Ответы с готовыми решениями:

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

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

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

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

1
Эксперт Java
3639 / 2971 / 918
Регистрация: 05.07.2013
Сообщений: 14,220
14.03.2019, 11:40 2
Цитата Сообщение от maksimka2112 Посмотреть сообщение
А через параллельные стримы будет оптимально? вот так, например:
ты же знаешь, что можешь запустить код и посмотреть? Скорее всего читать один файл в несколько потоков смысла нет
0
14.03.2019, 11:40
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
14.03.2019, 11:40
Помогаю со студенческими работами здесь

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru