meng jue
meng jue

Reputation: 55

Get different results using main and junit in java

When I tested a simple producer/consumer example, I got a very strange result as below.

  1. If I used main() to test the following code, I'll get the correct and expected result.
  2. But I only can get the 1st directory correctly, the remaining works were dropped by the JUnit.

What is the exact reason?

Working code:

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();
    }
}

Bad Code:

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();
    }
}

Other function code:

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);

    }
}

Upvotes: 2

Views: 367

Answers (1)

Thomas W
Thomas W

Reputation: 14164

Junit's presumably allowing the JVM & threads to terminate, once the test is finished -- thus your threads do not complete working.

Try waiting for the threads to 'join':

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();

This should help.

.. The other thing that can go wrong, is that log output (via Log4J) can sometimes be truncated at the end of execution; flushing & pausing can help. But I don't think that will affect you here.

Upvotes: 3

Related Questions