从生产者/消费者模型中的文件中读取

时间:2018-05-02 19:33:43

标签: java multithreading producer-consumer

我尝试从文件中读取字符串,使用该字符串执行HTTP请求,如果请求返回200,则使用它执行另一个HTTP请求。

我认为一个好的模型就是生产者消费者模型,但出于某种原因,我完全陷入困境。由于某种原因,整个过程在某个时刻停止,我不知道为什么。

public static void main(String[] args) throws InterruptedException, IOException {

    ArrayBlockingQueue<String> subQueue = new ArrayBlockingQueue<>(3000000);

    ThreadPoolExecutor consumers = new ThreadPoolExecutor(100, 100, 10000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10));
    ThreadPoolExecutor producers = new ThreadPoolExecutor(100, 100, 10000, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(10000000));
    consumers.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
    String fileName = "test";
    try (BufferedReader br = new BufferedReader(new FileReader(fileName))) {
        String line;
        while ((line = br.readLine()) != null) {
            String address = new JSONObject(line).getString("Address");
            producers.submit(new Thread(() -> {
                if (requestReturn200(address)) {
                    try {
                        subQueue.put(address);
                    } catch (InterruptedException e) {
                        System.out.println("Error producing.");
                    }
                }
            }));
        }
        producers.shutdown();
    }

    while (subQueue.size() != 0 || !producers.isShutdown()) {
        String address = subQueue.poll(1, TimeUnit.SECONDS);
        if (address != null) {
            consumers.submit(new Thread(() -> {
                try {
                    System.out.println("Doing..." + address);
                    doOtherHTTPReqeust(address);
                } catch (Exception e) {
                    System.out.println("Fatal error consuming);
                }
            }));

        } else {
            System.out.println("Null");
        }
    }

    consumers.shutdown();
}

非常感谢任何和所有帮助。

1 个答案:

答案 0 :(得分:2)

 while (subQueue.size() != 0 || !producers.isShutdown()) {

首先!producers.isShutdown()将始终返回!true,因为它会在producers.shutdown()之后进行检查。 isShutdown未说明池中的任务是否仍在运行,但如果池已关闭,则导致无法接受新任务。在您的情况下,这将始终是false

第二,subQueue.size() != 0虽然您的消费者创建循环和消费者从队列中获取的数据比生产者可以提供的快得多,但在生成&#34;生成&#34;过程中,消费者可能已经明确了这种情况,导致条件subQueue.size!=变得虚伪。如你所知,这将破坏生产者的循环和转发。

您应该停止使用queue.size(),而是使用BlockingQueue的屏蔽属性。 queue.take()将阻止,直到新元素可用。

所以整体流程应该是这样的。

  1. 启动一些生产者任务池,就像你现在正在做的那样。
  2. 让生产者将数据放入阻塞队列 - 是的,你在这里
  3. 启动一些(我会说固定的)消费者数量
  4. 让消费者queue.take()数据来自队列。这将迫使消费者进行自动消毒。对于新数据,并在它可用时接受它。
  5. 我会撇开提到创建200个线程是疯狂的,并且错过了多线程消费者/生产者/任务池的整个目的,至少在你的情况下是恕我直言。我们的想法是使用少量线程,因为它们是重量级的,可以执行大量排队任务。但这是不同时间的讨论。