2012-04-20 50 views
2

我想第一次使用java期貨。我有一個課程設置爲解壓縮一些文件。想要遞歸解壓縮,因爲我有zip文件包含zip文件。使用Java期貨的線程安全集合操作

我有一個驅動器類,實例化一個實現可調用的Uncompressor類。解壓縮器開始解壓縮,如果遇到另一個.zip,它會創建一個自己的實例,將其添加到池中,然後繼續。

僞代碼

From DriverClass: 

. 
. 
. 
ExecutorService pool = new Executors.newFixedThreadPool(4); 
Uncompressor uc = new Uncompressor(pool, compressedFile); 
Collection<File> files = uc.uncompress(); 
for(Future <Collection<File>> f : uc.futures) 
    files.addAll(f.get()); 
// at the end of this loop, files doesnt seem to hold all of my files 

這裏是我的uncompressor類

public class Uncompressor implements Callable<Collection<File>> 
{ 
    public Set<Future<Collection<File>>> futures = new HashSet<Future<Collection<File>>>(); 
    File compressedFile; 
public Uncompressor(ExecutorService pool, File compressedFile) 
{ 
    this.pool = pool; 
    this.compressedFile = compressedFile; 
} 

public Collection<File> call() throws Exception[ 
    return uncompress(); 
} 

public Collection<File> uncompress() 
{ 
List<File> uncompressedFiles = new ArrayList<File>(); 
. 
.Loop 
.//Try to uncompress the file. If the archive entry is a zip file, do the following: 

    Callable<Collection<File>> callable = new Uncompressor(this.pool, archiveFileEntry); 
    Future f = pool.submit(callable); 
    futures.add(f); 

//else, add files to a collection here for returning 
uncompressedFiles.add(archiveFileEntry); 

.EndLoop 

return uncompressedFiles; 
. 
. 
} 

所以,問題是我DriverClass,我的文件的採集應保存所有未壓縮的文件從遞歸在這裏下潛似乎並沒有包含所有的文件。我認爲我在從未來獲取返回值時做錯了什麼。是否因爲我定義了一個類成員變量futures

謝謝

+0

是的,這是可能的。它可以是zip內的任意數量的zip,真的是 – Derek 2012-04-20 15:08:09

回答

3

,如果你有嵌套大於1的深度您的代碼將無法正常工作,即頂層壓縮包含帶有拉鍊拉鍊。在這種情況下,您的頂級Uncompressor將沒有底層zip文件的未來。

對此,使用ForkJoinPool會很酷,因爲它更適合遞歸式任務分解。 Java 7的不是一個選項,但是,我會做的就是改變Uncompressor,這樣的結果是期貨和文件的元組,然後更改主叫方保留所有未平倉期貨的軌跡:

--Caller-- 

Collection<File> alluncompressedFiles = new HashSet<File>(); 
Collection<Future<UncompressorResult>> futures = new LinkedList<Future<UncompressorResult>>(); 
Future<UncompressorResult> future = pool.submit(new Uncompressor(pool, compressedFile)); 
futures.add(future); 

while (!futures.isEmpty()) { 
    Future<UncompressorResult> future = futures.poll(); 
    UncompressorResult result = future.get(); 

    futures.addAll(result.getFutures()); 
    uncompressedFiles.addAll(result.getFiles()); 
} 

和解壓縮器更改如下:

public UncompressorResult call() throws Exception[ 
    List<File> uncompressedFiles = new ArrayList<File>(); 

    for (File entry : zipFiles) { 
     if (entry is not ZIP) { 
      uncompressedFiles.add(entry); 
     } else { 
      Callable<UncompressorResult> callable = new Uncompressor(this.pool, entry); 
      Future<UncompressorResult> f = pool.submit(callable); 
      futures.add(f); 
     } 
    } 

    return new UncompressorResult(uncompressedFiles, futures; 
} 
+0

根據我能找到的文檔,ForkJoinTask是Java 7的一部分嗎?我尚未使用該版本。 – Derek 2012-04-20 15:24:13

+0

是的,它是Java 7.這不是一個選項,你可以重新編寫調用者循環,直到沒有zip文件。我會編輯我的答案。 – sharakan 2012-04-20 15:34:00

+0

這樣做有什麼區別,並使期貨返回收集?是不是比讓Tuple基本上有一個空洞的未來,加上一個文件集合更容易?另外,在您的代碼中,我的調用方法必須是Collection 而不是UncompressorResult,對吧?因爲我的類將不得不實現Callable 而不是Callable > – Derek 2012-04-20 19:46:54