javamultithreadingfilefork-join

How can I add "Fork-join" to my file search code?


I wrote a program that searches for the necessary files in a directory and its subfolders based on the desired file size. But according to the assignment, I need to add a multithreaded "Fork-join" mode. I understand that he can slow down, not speed up the work, but this was my assignment. I can't add it to the code in any way to make everything work.

import java.io.File;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Scanner;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class  Main{
    static Scanner in = new Scanner(System.in);
    static File directory = new File(in.next());
    public static final double MIN_LENGTH = in.nextDouble() * 1048576;  
    static int numOfThreads = 2; 



    public static void main(String[] args) {
        ArrayList<File> fileList = new ArrayList<>();
        getFiles(directory, fileList);
        fileList.sort(Comparator.<File>comparingLong(File::length).reversed());
        DecimalFormat df = new DecimalFormat("#.#");
        ForkJoinPool pool = new ForkJoinPool(numOfThreads);



        for(File file: fileList) {

            if(file.length()>= 1073741824) {
                double Gb = (double) file.length() / 1073741824;
                System.out.printf("%s Gb  %s%n", df.format(Gb), file); 
            } else if(file.length()>= 1048576) {
                System.out.printf("%s Mb  %s%n", file.length() / 1048576, file); 
            } else if (file.length()>= 1024){
                System.out.printf("%s Kb  %s%n", file.length() / 1024, file);  
            } else if (file.length()< 1024){
                System.out.printf("%s B  %s%n", file.length(), file); 
            } else {
                System.out.printf("%s Gb  %s%n", file.length() / (1073741824 * 1024), file); 
            }
        }
    }

    private static void getFiles(File rootFile, List<File> fileList) {
        if (rootFile.isDirectory()) {
            File[] directoryFiles = rootFile.listFiles();
            if (directoryFiles != null) {
                for (File file: directoryFiles) {
                    if (file.isDirectory()) {
                        getFiles(file, fileList);
                    } else {
                        if (file.isFile() && file.length() >= MIN_LENGTH) {
                            fileList.add(file);
                        }
                    }
                }
            }
        }
    }
}

I tried to divide the work into 2 threads, the first thread processes files up to 5 megabytes, and the second one connects if the file is larger than 5 megabytes, but everything turned out crookedly and does not work


Solution

  • I think the idea is that each task should process a single file/directory.

    Example:

        ForkJoinPool pool = new ForkJoinPool(20);
        FileTask task = new FileTask(directory);
        pool.invoke(task);
    

    class FileTask:

    public class FileTask extends RecursiveAction {
        private final DecimalFormat df = new DecimalFormat("#.#");
        private final File file;
    
        public FileTask(File file) {
            this.file = file;
        }
    
        @Override
        protected void compute() {
            if (file.isDirectory()) {
                processDir();
            } else if (file.isFile()) {
                processFile();
            }
        }
    
        private void processFile() {
            if(file.length()>= 1073741824) {
                double Gb = (double) file.length() / 1073741824;
                System.out.printf("%s Gb  %s%n", df.format(Gb), file); 
            } else if(file.length()>= 1048576) {
                System.out.printf("%s Mb  %s%n", file.length() / 1048576, file); 
            } else if (file.length()>= 1024){
                System.out.printf("%s Kb  %s%n", file.length() / 1024, file);  
            } else if (file.length()< 1024){
                System.out.printf("%s B  %s%n", file.length(), file); 
            } else {
                System.out.printf("%s Gb  %s%n", file.length() / (1073741824 * 1024), file); 
            }
        }
    
        private void processDir() {
            List<FileTask> tasks = new ArrayList<>();
            File[] subFiles = file.listFiles();
            for (File sub: subFiles) {
                tasks.add(new FileTask(sub));
            }
            ForkJoinTask.invokeAll(tasks);
        }
    }