Java阻塞队列take()和poll()方法的区别

39
在无限循环中从队列中提取值时,哪种方法更有效:
1.在队列上阻塞直到通过take()获得可用的值
while (value = queue.take()) { doSomething(value); }
  • 睡眠n毫秒并检查项目是否可用

  • while (true) {
        if ((value = queue.poll()) != null) { doSomething(value); }
        Thread.sleep(1000);
    }
    

    1
    根据我的经验,线程是将消息生产/消费到阻塞队列中的最佳方式。 - Karthikeyan Sukkoor
    Java如何使用赋值语句作为条件来实现while循环? - davidchoo12
    “高效”可以有很多方面:更低的延迟、更高的吞吐量、更少的能源消耗(移动设备),等等。如果您提供更多的背景信息,您将得到更适合的答案。 - Renan
    "while (value = queue.take()) { doSomething(value); }" 这段代码是如何工作的? - Adelin
    2个回答

    65

    阻塞可能更有效率。在后台,最初调用take()的线程如果没有元素可用,则会进入睡眠状态,让其他线程执行它们需要执行的操作。向队列添加元素的方法将在添加元素时唤醒等待的线程,这样就不必一遍又一遍地检查队列是否有元素可用。


    20
    最好使用带有超时的解决方案,以避免线程在不确定的时间内被阻塞。因此,一个好的实现是使用 poll(timeout, unit),特别是如果线程由线程池运行并等待其他任务执行。 - Pierrick
    3
    但是,take() 方法本质上不就是睡眠指定的时间(即直到有另一个可用任务)吗?在我看来,poll(timeout,unit) 方法将实现相同的功能,只不过它会不必要地唤醒并执行检查。 - Nom1fan

    2

    使用take()时要小心。如果您正在从一个带有数据库连接的服务中使用take(),那么请注意。

    如果在过期时间后返回take(),它将抛出"Stale connection exception"异常。

    使用poll来等待预定义的时间,并对返回的对象进行空值检查。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接