【问题标题】:java & threads: interrupted exceptions & how to properly use BlockingQueue's take() methodjava & 线程:被中断的异常 & 如何正确使用 BlockingQueue 的 take() 方法
【发布时间】:2010-11-10 13:50:02
【问题描述】:

当队列中没有任何内容并且调用了 take() 时,究竟会发生什么。 API 说该方法将等待,但这是否意味着 CPU 会旋转检查是否为空/非空,直到有项目在队列中,或者是否意味着线程产生并会被中断唤醒?如果是前者,我可能想看看队列是否为空,以及是否调用 thread.yield() 以放弃处理器时间。我的问题是我真的需要调用 yield 还是有一些内部机制为我处理?

其次,被中断的异常是什么意思?如果我理解正确,这意味着如果线程 A 正在执行此方法并且正在等待输入并且另一个线程 B 调用 threadA.interrupt() 那么线程 A 将捕获中断的异常并可能暂停执行,如果它很好的话。这是正确的思考方式吗?

【问题讨论】:

标签: java multithreading interrupted-exception


【解决方案1】:

注意 BlockingQueue 是一个接口。所以接下来是依赖于实现的。如果您查看(比如说)LinkedBlockingQueue 的源代码,take() 的源代码会在 RentrantLock 上调用 lockInterruptibly()。来自doc

如果锁不可用,则 当前线程被禁用 线程调度的目的和谎言 休眠直到两件事之一 发生:

* The lock is acquired by the current thread; or
* Some other thread interrupts the current thread, and interruption of

支持锁定获取。

我怀疑有一些 wait()/notify() 或类似的事情正在发生。它会旋转CPU吗?否(通过top 或类似方式检查)

回复。关于中断的问题,Java 专家时事通讯在interrupt() 上有一个very interesting article 并捕获/处理InterruptedException

阅读这篇文章,但本质上,如果你发现异常,你就会重新中断:

  try {
        Thread.sleep(1000);
      } catch (InterruptedException ex) {
        Thread.currentThread().interrupt(); // very important
        break;
      }

【讨论】:

    【解决方案2】:

    调用 yield() 被认为是一种不好的做法,因为它不能确保 niceness - 你可以调用它,调度程序会立即返回到你的线程,因为它是无操作的。请改用定时等待(例如 wait(1000))。

    中断是一种安全的方式来向线程发出您想要从中获得某些东西的信号 - 停止处理、唤醒和响应某些东西等。

    一般来说,这些事情取决于您的具体情况。 Java 有一些很好的并发特性,可以更适用于某种情况。

    【讨论】:

    • 使用繁忙循环是不好的做法。如果你仍然使用繁忙的循环,那么使用 Thread.yield() 比不使用更好。
    • 这是由于其性质导致 yield 变成繁忙循环的问题。想象一个在双核 CPU 上运行的 2 线程应用程序。在任一线程中屈服都是无用且毫无意义的。使用 await/signal 总是更好的选择
    【解决方案3】:

    wait() 调用不会旋转,它通常使用操作系统服务来等待事件/条件 - 这会使线程进入睡眠状态,直到再次发出条件/事件信号。等待时不使用处理器时间。

    如果线程在 wait() 调用中阻塞,并且另一个线程在该阻塞线程上调用 interrupt(),通常会得到中断异常,就像你说的那样。

    【讨论】:

    • 我怎么知道等待事件/条件会使线程进入睡眠状态?换句话说,api 没有说线程将被置于睡眠状态并被通知唤醒,所以我怎么知道该方法实际上会做什么?
    • 您查看源代码,该源代码可从 Sun 获得。如果您使用的是其他 Java 实现,我不知道。
    • 你不知道,因为 API 并没有明确告诉你。但是,您可以编写一个挂起的测试程序并分析程序和/或操作系统以查看它在等待时是否占用 CPU。我知道没有 jvm/os 组合可以进行主动旋转
    猜你喜欢
    • 1970-01-01
    • 2010-10-23
    • 2014-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-23
    • 1970-01-01
    相关资源
    最近更新 更多