Java: Как реализовать многопоточность в рекурсивном алгоритме поиска размера папки? - PullRequest
0 голосов
/ 11 июня 2018

Итак, я уже разработал однопотоковую версию искателя размера папок, но чтобы сделать его более интересным, я хотел повысить его скорость и, надеюсь, развить мое понимание многопоточных процессов.Однако после ~ 30 ревизий всегда возникала проблема, была ли это:
- что основной поток печатал результат до того, как все потоки были выполнены
- Длинный тип переполнялся, когда его не должно было иметь (возможно двойноеможет считаться)
- многопоточная версия занимает больше времени, чем однопоточная версия

Я в растерянности, я не знаю, не подходит ли такая проблема для многопоточности илиесли я ошибаюсь.Я разместил мою самую «успешную» ревизию ниже.

Я понимаю, что он технически запускается, а затем сразу же присоединяется к рабочему потоку, что делает его почти хуже, чем одиночный шаг.Однако это единственный способ получить основной поток для отображения правильного результата.

Поэтому моя главная проблема - заставить рабочий поток присоединиться только в конце, заставить его параллельно исследовать все подпапки, а затем соединиться с основным потоком, чтобы отобразить правильный результат.

package sizeBrowserCode;

import java.io.File;
import java.io.FileWriter;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;


public class Main {
static long lengthy;
static Thread worker;
static long sum;

private static long getLength() {
    return Main.lengthy;
}

private static void setLength(long var) {
    Main.lengthy=var;
}

private static long getFolderSize(File folder) {
    long length=0;
    File[] files = folder.listFiles();

    int count = files.length;

    for (int i = 0; i < count; i++) {
        if (files[i].isFile()) {
            length += files[i].length();
        }
        else {
            length += getFolderSize(files[i],true);
        }
    }
    System.out.println(folder+" // "+length);

    return length;
}

private static long getFolderSize(File folder,boolean multiThreaded) {
    if(multiThreaded) {
        long length;
        worker=new Thread(new Runnable() {
             public void run() {

                setLength(getFolderSize(folder));
                 }
                });
            worker.start();
            try {
                worker.join();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            length=getLength();
        return length;

    }else {
        return getFolderSize(folder);
    }
}


public static String convert_Bytes(long bytes,String prefered_Unit) {
    prefered_Unit=prefered_Unit.toLowerCase().trim();
    switch (prefered_Unit) {
    case "b": return (bytes+" Bytes");
    case "kb": return (bytes/1024+" Kilobytes");
    case "mb": return (bytes/Math.pow(1024,2)+" Megabytes");
    case "gb": return (bytes/Math.pow(1024,3)+" Gigabytes");
    case "tb": return (bytes/Math.pow(1024,4)+" Terabytes");
    default:System.out.println("Incorrect notation; Please use\nb\nkb\nmb\ngb\ntb");
            System.exit(0);
            return null;

    }
}

public static String convert_Bytes(long bytes) {
    double Kb=0;
    double Mb=0;
    double Gb=0;
    double Tb=0;
    String result;
    if (bytes>=1024) {
        Kb=bytes/1024;
        bytes=0;
        result=" Kilobytes";
        if(Kb>=1024) {
            Mb=Kb/1024;
            Kb=0;
            result=" Megabytes";
            if(Mb>=1024) {
                Gb=Mb/1024;
                Mb=0;
                result=" Gigabytes";
                if(Gb>=1024) {
                    Tb=Gb/1024;
                    Gb=0;
                    result=" Terabyte";
                }
            }
        }
    }else {
        result=" Bytes";
    }
    double sum=bytes+Mb+Gb+Tb;
    return (sum+result);
}

public static void main(String[] args) {

    String chosen_Folder =args[0];
    String prefered_Unit;
    String full_Size;
    try {
        prefered_Unit =args[1];
    }catch (Exception e) {
        prefered_Unit=null;
    }

    String local_Folder=System.getProperty("user.dir");
    File full_Path;
    String backslash   ="\\";
    String forwardslash="/";
    String seperater;
    if(System.getProperty("os.name").toLowerCase().indexOf("win")>=0) {
        seperater=backslash;
    }else {
        seperater=forwardslash;
    }
    full_Path=new File(local_Folder+seperater+chosen_Folder);



    System.out.println(full_Path);
    long startTime =System.nanoTime();
    if(prefered_Unit!=null) {
        full_Size=convert_Bytes(getFolderSize(full_Path),prefered_Unit);

    }else {
        full_Size=convert_Bytes(getFolderSize(full_Path));
    }
    long endTime =System.nanoTime();

    System.out.println("The size of "+chosen_Folder+" is: "+full_Size);
    System.out.println("Took "+TimeUnit.NANOSECONDS.toSeconds(endTime-startTime)+" seconds to execute.");
    File size_Indicator = new File(full_Path+seperater+"FileSize.txt");
    try {
    size_Indicator.createNewFile();
    FileWriter writer = new FileWriter(size_Indicator);
    writer.write(full_Size);
    writer.close();
    }catch(Exception e) {
        System.err.println(e);
    }

}

}

1 Ответ

0 голосов
/ 11 июня 2018

Просто для дополнения других ответов.

Старайтесь избегать использования

worker = new Thread(new Runnable() {
    ...
  }

Используйте вместо этого исполнителя.Их гораздо проще использовать, планировать, запускать и возвращать свои результаты.Кроме того, они заботятся о пуле потоков и других накладных расходах.

Чтение this .

Исполнители доступны начиная с Java 5 и являются неотъемлемой частью любой JVM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...