永无止境的线程

时间:2014-03-06 18:06:54

标签: java multithreading io blockingqueue

这是我的代码:

   public class BigFileReader implements Runnable {
    private final String fileName;
    int a = 0;

    private final BlockingQueue<String> linesRead;
    public BigFileReader(String fileName, BlockingQueue<String> linesRead) {
        this.fileName = fileName;
        this.linesRead = linesRead;
    }
    @Override
    public void run() {
        try {
            //since it is a sample, I avoid the manage of how many lines you have read
            //and that stuff, but it should not be complicated to accomplish
            BufferedReader br = new BufferedReader(new FileReader(new File("E:/Amazon HashFile/Hash.txt")));
            String str = "";

            while((str=br.readLine())!=null)
            {
                linesRead.put(str);
                System.out.println(a);
                a++;
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        System.out.println("Completed");
    }
}





public class BigFileProcessor implements Runnable {
    private final BlockingQueue<String> linesToProcess;
    public BigFileProcessor (BlockingQueue<String> linesToProcess) {
        this.linesToProcess = linesToProcess;
    }
    @Override
    public void run() {
        String line = "";
        try {
            while ( (line = linesToProcess.take()) != null) {
                //do what you want/need to process this line...
                String [] pieces = line.split("(...)/g");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}





public class BigFileWholeProcessor {
    private static final int NUMBER_OF_THREADS = 2;
    public void processFile(String fileName) {

        BlockingQueue<String> fileContent = new LinkedBlockingQueue<String>();
        BigFileReader bigFileReader = new BigFileReader(fileName, fileContent);
        BigFileProcessor bigFileProcessor = new BigFileProcessor(fileContent);
        ExecutorService es = Executors.newFixedThreadPool(NUMBER_OF_THREADS);
        es.execute(bigFileReader);
        es.execute(bigFileProcessor);
        es.shutdown();

    }
}

此代码很好,但存在一个主要问题。也就是说,线程永远不会结束!即使整个过程完成,我仍然可以使程序活着。这有什么不对?

2 个答案:

答案 0 :(得分:4)

BlockingQueue.take()将阻止,直到元素可用:

  

检索并删除此队列的头部,必要时等待,直到元素可用为止。

因此,在BigFileReader读完输入文件并在BlockingQueue上放置行之后,BigFileProcessor将在take()方法中永远等待新输入。

您可能希望找到一种向BigFileProcessor发出信号的方法,即BlockingQueue上不会再输入任何内容,可能是将a sentinel value添加到队列中或者找到其他方法告诉BigFileProcessor停止调用{ {1}}。

哨兵方法的一个例子:

take()

另一种方法可能是使用the overload of poll that takes a timeout value而不是public class BigFileReader implements Runnable { public static final String SENTINEL = "SENTINEL"; //the actual value isn't very important ... while((str=br.readLine())!=null) { linesRead.put(str); } //when reading the file is done, add SENTINEL to the queue linesRead.put(SENTINEL); } //inside BigFileProcessor... while ( (line = linesToProcess.take()) != null) { // check if value in queue is sentinel value if (line == BigFileReader.SENTINEL) { //break out of the while loop break; } //otherwise process the line as normal } ,并且逻辑是BigFileProcessor如果无法从队列中读取任何内容超过N秒等,则会破坏它的循环。

答案 1 :(得分:0)

BlockingQueue,顾名思义,正在阻止。这意味着一旦执行queue.take(),线程就会挂起,直到队列中有东西要采取。为了终止线程,您需要使用队列.isEmpty()来知道队列中是否还有任何消息。我建议您在读完文件后发送End Of File消息,以便知道何时退出循环。