内容目录
4.3.2 停止选择过程
Selector
的API中的最后一个方法,wakeup()
,提供了使线程从被阻塞的select()
方法中优雅地退出的能力:
public abstract class Selector { // 这里仅列出部分API public abstract void wakeup(); }
有三种方式可以唤醒在select()
方法中睡眠的线程:
- 调用wakeup()
-
调用
Selector
对象的wakeup()
方法将使得选择器上的第一个还没有返回的选择操作立即返回。如果当前没有在进行中的选择,那么下一次对select()
方法的一种形式的调用将立即返回。后续的选择操作将正常进行。在选择操作之间多次调用wakeup()
方法与调用它一次没有什么不同。有时这种延迟的唤醒行为并不是您想要的。您可能只想唤醒一个睡眠中的线程,而使得后续的选择继续正常地进行。您可以通过在调用
wakeup()
方法后调用selectNow()
方法来绕过这个问题。尽管如此,如果您将您的代码构造为合理地关注于返回值和执行选择集合,那么即使下一个select()
方法的调用在没有通道就绪时就立即返回,也应该不会有什么不同。不管怎么说,您应该为可能发生的事件做好准备。 - 调用 close()
-
如果选择器的
close()
方法被调用,那么任何一个在选择操作中阻塞的线程都将被唤醒,就像wakeup()
方法被调用了一样。与选择器相关的通道将被注销,而键将被取消。 - 调用 interrupt()
-
如果睡眠中的线程的
interrupt()
方法被调用,它的返回状态将被设置。如果被唤醒的线程之后将试图在通道上执行I/O操作,通道将立即关闭,然后线程将捕捉到一个异常。这是由于在第三章中已经探讨过的通道的中断语义。使用wakeup()
方法将会优雅地将一个在select()
方法中睡眠的线程唤醒。如果您想让一个睡眠的线程在直接中断之后继续执行,需要执行一些步骤来清理中断状态(参见Thread.interrupted()
的相关文档)。Selector
对象将捕捉InterruptedException
异常并调用wakeup()方法。
请注意这些方法中的任意一个都不会关闭任何一个相关的通道。中断一个选择器与中断一个通道是不一样的(参见 3.3 节)。选择器不会改变任意一个相关的通道,它只会检查它们的状态。当一个在select()
方法中睡眠的线程中断时,对于通道的状态而言,是不会产生歧义的。
0 条评论
撰写评论