如何使生产者线程等待消费者线程完成

时间:2016-06-07 11:14:56

标签: java multithreading

每个操作都将在我们的应用程序中创建主线程,该线程将创建任务并由 ExecutorService 提交。

目前,这些生产者线程将向ArrayList添加任务,来自threadPool的线程将执行任务。

在高负荷期间(当有许多操作时),我得到" Jvm内存不足" 错误。

如何通过让主线程根据某些限制等待一段时间来避免这种情况?

2 个答案:

答案 0 :(得分:2)

内存不足是另一个问题,但您需要producer/consumer with blocking queue

如果执行程序池中的消费线程无法足够快地处理请求,则阻塞队列将填满。一旦它完整,生产者将被阻止添加新任务,直到消费者可以处理请求并腾出空间。

这可能无法解决您的OOM问题。您需要分析代码以查看内存的使用情况。也许您的消费者线程在完成后无法清理,或者GC没有回收静态数据。

这可能是Sorcerer's Apprentice之类的情况。如果生产者如此快速地创建请求而不停止ArrayList无限延伸直到消耗掉所有内存,则会收到OOM错误。如果这是根本原因,那么阻止deque将解决它。

答案 1 :(得分:0)

如果您正在使用ExecutorService来执行任务,那么我建议您通过使用所需的配置实例化ThreadPoolExecutor,而不是默认的线程池实现,您可以使用自定义配置定义自己的线程池。见下文:

/**
     * Creates a new {@code ThreadPoolExecutor} with the given initial
     * parameters and default thread factory and rejected execution handler.
     * It may be more convenient to use one of the {@link Executors} factory
     * methods instead of this general purpose constructor.
     *
     * @param corePoolSize the number of threads to keep in the pool, even
     *        if they are idle, unless {@code allowCoreThreadTimeOut} is set
     * @param maximumPoolSize the maximum number of threads to allow in the
     *        pool
     * @param keepAliveTime when the number of threads is greater than
     *        the core, this is the maximum time that excess idle threads
     *        will wait for new tasks before terminating.
     * @param unit the time unit for the {@code keepAliveTime} argument
     * @param workQueue the queue to use for holding tasks before they are
     *        executed.  This queue will hold only the {@code Runnable}
     *        tasks submitted by the {@code execute} method.
     * @throws IllegalArgumentException if one of the following holds:<br>
     *         {@code corePoolSize < 0}<br>
     *         {@code keepAliveTime < 0}<br>
     *         {@code maximumPoolSize <= 0}<br>
     *         {@code maximumPoolSize < corePoolSize}
     * @throws NullPointerException if {@code workQueue} is null
     */
    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue) {
    }

在这里,您可以提供自己的BlockingQueue,其大小由您定义,所以现在在这种情况下,当队列已满时,其他新任务将等待,直到队列有空间接受新任务。

通过此实现,您可以根据需要控制和调整线程池。

你可以点击这个link获取更多详细信息,你可能会觉得它很无聊:P,但相信我,你会发现它非常有用,一旦你阅读它,所以只是耐心地阅读.. :))