当队列中没有任何内容并调用take()时会发生什么。 API表示该方法将等待,但这是否意味着CPU在队列中出现一个项目或者是否意味着线程会被中断唤醒之前,旋转检查是否为空/非空?如果是前者的情况,我可能想看看队列是否为空以及是否调用thread.yield()来放弃处理器时间。我的问题是,我是否需要调用yield或者是否有一些内部机制为我处理?
其次,中断的异常意味着什么?如果我理解正确,这意味着如果线程A正在执行此方法并且正在等待输入而另一个线程B调用threadA.interrupt(),那么线程A将捕获中断的异常并且可能会暂停执行,如果它很好的话。这是正确的思考方式吗?
答案 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有一些很好的并发特性,可以更适用于某种情况。