How to read multiple txt files into one List with multithread?

Viewed 85

I am learning multithread in Java. To practice, I want do multithread to read three txt files in paralel, adding each line of three files into one List. This is my code:

ArrayList<String> allLinesFromFiles= new ArrayList<String>();
Lock blockThread=new ReentrantLock();
Thread t = null;
    for (String file : files) {
        
        t= new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    FileReader fichero;
                    fichero = new FileReader(file);
                    BufferedReader bufferFichero = new BufferedReader(fichero);
                    String line = bufferFichero.readLine();
                    
                    while (line != null) {
                        writeList(line.toLowerCase());
                        line = bufferFichero.readLine();
                    }
            
                    bufferFichero.close();
                    
                }catch (IOException e) {
                    System.out.println("Error IO");
                }
            }
            
            private void writeList(String line) {
                blockThread.lock();
                allLinesFromFiles.add(line);
                blockThread.unlock();
            }
        });
        t.start();  
    }
    try {
        t.join();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    Collections.sort(allLinesFromFiles);

I used lock/unlocks (ReentrantLock) in the method "writeList" to synchronize because three threads writting in the ArrayList I thought maybe is needed. Is correct? Have I to use CopyOnWriteArrayList instead of ArrayList?

I used join() to wait the finish of three threads but my code dont work correctly.

1 Answers

A simple way base on your code is to add an AtomicInteger count to know if the read Thread is ended or not,and the Main Thread wait for the end:

List<String> files = Arrays.asList("a.txt", "b.txt", "c.txt");
                ArrayList<String> allLinesFromFiles= new ArrayList<String>();
                Lock blockThread=new ReentrantLock();
                AtomicInteger count = new AtomicInteger(0); // counter
                Thread t = null;
                for (String file : files) {
                        t= new Thread(new Runnable() {
                                @Override
                                public void run() {
                                        try {
                                                FileReader fichero;
                                                fichero = new FileReader(getClass().getClassLoader().getResource(file).getFile());
                                                BufferedReader bufferFichero = new BufferedReader(fichero);
                                                String line = bufferFichero.readLine();

                                                while (line != null) {
                                                        writeList(line.toLowerCase());
                                                        line = bufferFichero.readLine();
                                                }

                                                bufferFichero.close();
                                        }catch (IOException e) {
                                                e.printStackTrace();
                                                System.out.println("Error IO");
                                        }finally {
                                                count.getAndIncrement(); // counter ++
                                        }
                                }

                                private void writeList(String line) {
                                        blockThread.lock();
                                        allLinesFromFiles.add(line);
                                        blockThread.unlock();
                                }
                        });
                        t.start();
                }
                while (count.intValue() < 3) {
                        TimeUnit.MILLISECONDS.sleep(500);
                }
                Collections.sort(allLinesFromFiles);
                System.out.println(allLinesFromFiles);

But, a better way is:

List<String> filePaths = Arrays.asList("a.txt", "b.txt", "c.txt");
                List<String> result = new ArrayList<>();
                filePaths.parallelStream().forEach(filePath -> {
                        try {
                                List<String> strings = Files.readAllLines(
                                        Paths.get(ReadTest.class.getClassLoader().getResource(filePath).toURI()));
                                result.addAll(strings);
                        } catch (IOException | URISyntaxException e) {
                                e.printStackTrace();
                        }
                });
                Collections.sort(result);
                System.out.println(result);
Related