2

単純なプロデューサー/コンシューマーの例をテストしたところ、以下のような非常に奇妙な結果が得られました。

  1. main() を使用して次のコードをテストした場合、正しい期待どおりの結果が得られます。
  2. しかし、最初のディレクトリしか正しく取得できず、残りの作業は JUnit によって削除されました。

正確な理由は何ですか?

作業コード:

import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.junit.Test;

public class TestProducerAndConsumer {

    public static void main(String[] args) {
        BlockingQueue<File> queue = new LinkedBlockingQueue<File>(1000);

        new Thread(new FileCrawler(queue, new File("C:\\"))).start();
        new Thread(new Indexer(queue)).start();
    }
}

悪いコード:

import java.io.File;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

import org.junit.Test;

public class TestProducerAndConsumer {

    @Test
    public void start2() {
        BlockingQueue<File> queue = new LinkedBlockingQueue<File>(1000);

        new Thread(new FileCrawler(queue, new File("C:\\"))).start();
        new Thread(new Indexer(queue)).start();
    }
}

その他の機能コード:

import java.io.File;
import java.util.Arrays;
import java.util.concurrent.BlockingQueue;

public class FileCrawler implements Runnable {
    private final BlockingQueue<File> fileQueue;
    private final File root;
    private int i = 0;

    public FileCrawler(BlockingQueue<File> fileQueue, File root) {
        this.fileQueue = fileQueue;
        this.root = root;
    }

    @Override
    public void run() {
        try {
            craw(root);
        } catch (InterruptedException e) {
            System.out.println("shit!");
            e.printStackTrace();
            Thread.currentThread().interrupt();
        }

    }

    private void craw(File file) throws InterruptedException {
        File[] entries = file.listFiles();
        //System.out.println(Arrays.toString(entries));
        if (entries != null && entries.length > 0) {
            for (File entry : entries) {
                if (entry.isDirectory()) {
                    craw(entry);
                } else {
                    fileQueue.offer(entry);
                    i++;
                    System.out.println(entry);
                    System.out.println(i);
                }
            }
        }

    }

    public static void main(String[] args) throws InterruptedException {
        FileCrawler fc = new FileCrawler(null, null);
        fc.craw(new File("C:\\"));
        System.out.println(fc.i);
    }

}




import java.io.File;
import java.util.concurrent.BlockingQueue;

public class Indexer implements Runnable {

    private BlockingQueue<File> queue;

    public Indexer(BlockingQueue<File> queue) {
        this.queue = queue;
    }

    @Override
    public void run() {
        try {
            while (true) {
                indexFile(queue.take());
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }

    private void indexFile(File file) {
        System.out.println("Indexing ... " + file);

    }
}
4

1 に答える 1

3

Junit は、テストが終了すると、おそらく JVM とスレッドを終了できるようにしているため、スレッドは動作を完了しません。

スレッドが「参加」するのを待ってみてください:

Thread crawlerThread = new Thread(new FileCrawler(queue, new File("C:\\")));
Thread indexerThread = new Thread(new Indexer(queue));
crawlerThread.start();
indexerThread.start();
// 
// wait for them to finish.
crawlerThread.join();
indexerThread.join();

これは役立つはずです。

.. うまくいかない可能性があるもう 1 つの点は、ログ出力 (Log4J 経由) が実行の最後で切り捨てられることがあるということです。フラッシュと一時停止が役立ちます。しかし、それがここに影響を与えるとは思いません。

于 2013-05-05T11:31:57.607 に答える