2012-04-20 52 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