2

初めてJava先物を使用しようとしています。一部のファイルを解凍するためのクラスを設定しています。zipファイルを含むzipファイルがあるため、再帰的に解凍したい。

callable を実装する Uncompressor クラスをインスタンス化するドライブ クラスがあります。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

そして、ここに私のアンコンプレッサークラスがあります

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にあり、再帰的なダイビングからのすべての非圧縮ファイルを保持する必要があるファイルのコレクションには、すべてのファイルが含まれているようには見えません。Future から戻り値を取得する際に何か問題があると思います。クラスメンバー変数をfutures定義した方法が原因ですか?

ありがとうございました

4

1 に答える 1

3

入れ子の深さが 1 より大きい場合、つまり最上位の zip に zip を含む zip が含まれている場合、コードは機能しません。その場合、トップ レベルの 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());
}

Uncompressor は次のように変わります。

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;
}
于 2012-04-20T14:56:32.243 に答える