[英]How can I speed up my Java recursive file search on Windows?
我正在使用Java 8搜索文件目錄並提取音樂文件。 當我在Linux(Debian Wheezy)上運行代碼時,它會在20秒鍾左右完成。 但是,當我在Windows 8.1(同一台機器!)上運行相同的代碼時,要花費非常長的時間,時間如此之長,以至於它實際上是不可用的。 我已經確定該過程正在按預期進行,只是非常緩慢。 在Linux變體找到所有2500個文件的時候,Windows變體找到了大約100個。
這是代碼:
public int List(String path) throws InterruptedException, IOException {
//Linux Variant
if (HomeScreen.os.equals("Linux")) {
File root = new File(path);
File[] list = root.listFiles();
Arrays.sort(list);
if (list == null) {
return 0;
}
for (File f : list) {
if (f.isDirectory()) {
List(f.getAbsolutePath());
} else if (f.isFile()) {
String outPath = f.getAbsolutePath();
try {
String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3")) {
String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 6);
lm.addElement(fulltrack);
numbers++;
}
} catch (Exception e) {
System.out.println(outPath + " is not a valid file!!!!!");
}
HomeScreen.Library.setModel(lm);
}
}
//Windows variant
} else if (HomeScreen.os.equals("Windows 8.1")){
System.out.println("Using " + HomeScreen.os + " methods...");
File root = new File(path);
File[] list = root.listFiles();
Arrays.sort(list);
if (list == null) {
return 0;
}
for (File f : list) {
if (f.isDirectory()) {
List(f.getAbsolutePath());
} else if (f.isFile()) {
String outPath = f.getAbsolutePath();
try {
String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3")) {
String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 9);
lm.addElement(fulltrack);
numbers++;
}
} catch (Exception e) {
System.out.println(outPath + " is not a valid file!!!!!");
}
HomeScreen.Library.setModel(lm);
}
}
}
return numbers;
}
我對Java還是很陌生,所以我不確定如何為Windows優化代碼。 有什么辦法可以加快這種速度,還是Windows用戶注定要去喝咖啡並等待負載增加?
順便說一句,我在使用Windows時將此方法放在線程中,以便可以在等待時完成其他操作,但這絕對不是理想的解決方案。 要搜索的驅動器是一個7200 rpm的HDD,並且安裝了8GB RAM。
嘗試使用新的Java 8流API,它可以讓您在一個循環中執行所有操作(對每個過濾器進行排序)! 與並行:
這是您更改后的代碼(您可能需要修復我確實有的某些部分,例如HomeScreen)
Arrays.asList(root.listFiles())
.parallelStream()
.filter(file -> file != null)
.forEach(file -> {
if (file.isDirectory())
{
List(file.getAbsolutePath());
}
else if (file.isFile())
{
String outPath = file.getAbsolutePath();
try
{
String ext = outPath.substring(outPath.lastIndexOf(".") + 1);
if (ext.equals("wma") || ext.equals("m4a") || ext.equals("mp3"))
{
String fulltrack = outPath.substring(outPath.lastIndexOf("Music/") + 9);
lm.addElement(fulltrack);
numbers++;
}
} catch (Exception e)
{
System.out.println(outPath + " is not a valid file!!!!!");
}
HomeScreen.Library.setModel(lm);
}
});
正如在對Lorenzo Boccaccia所鏈接的問題的評論中所建議的那樣,我將選擇newDirectoryStream 。 它一個接一個地返回文件,應該更快。
我也會考慮使用多線程。 使用單個線程,您幾乎一直都在等待磁盤。 現代磁盤能夠處理多個未決請求,因此使用2-4個線程應該會有所幫助。
旁注:沒有理由針對Linux和Windows編寫不同的代碼。 可能需要進行一些細微的更改,但是應該使用一些小的輔助方法來進行處理。
絕對不要寫像
if (HomeScreen.os.equals("Linux")) {
...
} else if (HomeScreen.os.equals("Windows 8.1")) {
...
}
如果是“ Windows 8.2”怎么辦?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.