java&线程:中断的异常&如何正确使用BlockingQueue的take()方法

时间:2009-07-14 07:48:13

标签: java multithreading wait interrupt

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

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

3 个答案:

答案 0 :(得分:5)

请注意,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;
      }

答案 1 :(得分:4)

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

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

答案 2 :(得分:0)

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

中断是向线程发出信号的安全方式,您可以从中获取某些内容 - 停止处理,唤醒和响应某些内容等。

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