LinkedBlockingQueue只返回一个mupltiple线程

时间:2015-12-16 21:52:37

标签: java multithreading blockingqueue

我创建了一个类来计算同一目录中给定文件中的单词。看到文件非常大,我决定使用多个线程实现多个文件的计数。

当按照下面的指定运行DriverClass时,它会陷入第一个线程。 我究竟做错了什么?当我在queue.take()上进行迭代时,人们会期望解析器等待某些内容进行检索并继续前进。卡在线程1会让我怀疑将()放入队列时会出错。

提前谢谢!

DriverClass:

public class WordCountTest {
    public static void main(String[] args){
        if (args.length<1){
            System.out.println("Please specify, atleast, one file");
        }
        BlockingQueue<Integer> threadQueue = new LinkedBlockingQueue<>();
        Runnable r;
        Thread t;

        for (int i = 0; i<args.length; i++){
            r = new WordCount(args[i], threadQueue);
            t = new Thread(r);
            t.start();

            int total = 0;
            for (int k = 0; k<args.length; k++){
                try {
                    total += threadQueue.take();
                } catch (InterruptedException e){
                }
            }
            System.out.println("Total wordcount: " + total);
        }
    }
}

WordCountClass:

public class WordCount implements Runnable {
    private int myId = 0;
    private String _file;
    private BlockingQueue<Integer> _queue;
    private static int id = 0;

    public WordCount(String file, BlockingQueue<Integer> queue){
        _queue = queue;
        _file = file;
        myId = ++id;
    }

    @Override
    public void run() {
        System.out.println("Thread " + myId + " running");
        try {
            _queue.put(countWord(_file));
        } catch (InterruptedException e){

        }
    }

    public int countWord(String file){
        int count = 0;
        try {
            Scanner in = new Scanner(new FileReader(file));
            while (in.hasNext()){
                count++;
                in.next();
            }
        } catch (IOException e){
            System.out.println("File," + file + ",not found");
        }
        return count;
    }
}

2 个答案:

答案 0 :(得分:1)

您正在等待第一个线程启动后的所有结果。也许您打算在所有线程启动后等待结果。

注意:如果创建的线程数多于CPU数,则速度可能会变慢。我建议使用固定的线程池。

答案 1 :(得分:1)

问题是你正在使用嵌套循环,当你应该使用两个单独的循环时:一个用于启动WordCounts,另一个用于收集结果,例如

public class WordCountTest {
    public static void main(String[] args){
        Queue<Integer> threadQueue = new ConcurrentLinkedQueue<>();
        ExecutorService executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());

        CountDownLatch latch = new CountDownLatch(args.length);

        for (int i = 0; i<args.length; i++){
            CompletableFuture.runAsync(new WordCount(args[i], threadQueue), executor)
                .thenRunAsync(latch.countDown(), executor);
        }

        latch.await();

        int sum = 0;
        for(Integer i : threadQueue) {
            sum += i;
        }
    }
}

或者你想要实现它,关键是在所有WordCounts开始之前你不应该开始收集结果。