精华帖 (0) :: 良好帖 (1) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-10-22
NIO中的Selector封装了底层的系统调用,其中wakeup用于唤醒阻塞在select方法上的线程,它的实现很简单,在linux上就是创建一 个管道并加入poll的fd集合,wakeup就是往管道里写一个字节,那么阻塞的poll方法有数据可读就立即返回。证明这一点很简单,strace即 可知道:
public class SelectorTest { public static void main(String[] args) throws Exception { Selector selector = Selector.open(); selector.wakeup(); } }
sudo strace -f -e write java SelectorTest
输出:
Process 29181 attached Process 29182 attached Process 29183 attached Process 29184 attached Process 29185 attached Process 29186 attached Process 29187 attached Process 29188 attached Process 29189 attached Process 29190 attached Process 29191 attached [pid 29181] write(36, "\1", 1) = 1 Process 29191 detached Process 29184 detached Process 29181 detached
public class SelectorTest { public static void main(String[] args) throws Exception { Selector selector = Selector.open(); selector.wakeup(); selector.selectNow(); selector.wakeup(); selector.selectNow(); selector.wakeup(); } }
修改程序调用三次wakeup,心细的朋友肯定注意到我们还调用了两次selectNow,这是因为在两次成功的select方法之间调用wakeup多
次都只算做一次,为了显示3次write,这里就每次调用前select一下将前一次写入的字节读到,同样执行上面的strace调用,输出:
Process 29303 attached Process 29304 attached Process 29305 attached Process 29306 attached Process 29307 attached Process 29308 attached Process 29309 attached Process 29310 attached Process 29311 attached Process 29312 attached Process 29313 attached [pid 29303] write(36, "\1", 1) = 1 [pid 29303] write(36, "\1", 1) = 1 [pid 29303] write(36, "\1", 1) = 1 Process 29313 detached Process 29309 detached Process 29306 detached Process 29303 detached
public class SelectorTest { public static void main(String[] args) throws Exception { Selector selector = Selector.open(); selector.wakeup(); selector.wakeup(); selector.wakeup(); } }
Process 29331 attached Process 29332 attached Process 29333 attached Process 29334 attached Process 29335 attached Process 29336 attached Process 29337 attached Process 29338 attached Process 29339 attached Process 29340 attached Process 29341 attached [pid 29331] write(36, "\1", 1) = 1 Process 29341 detached Process 29337 detached Process 29334 detached Process 29331 detached
public void interrupt() { interrupt(outgoingInterruptFD); } 实际调用的是interrupt(fd)的native方法,查看EPollArrayWrapper.c可见清晰的write系统调用: JNIEXPORT void JNICALL Java_sun_nio_ch_EPollArrayWrapper_interrupt(JNIEnv *env, jobject this, jint fd) { int fakebuf[1]; fakebuf[0] = 1; if (write(fd, fakebuf, 1) < 0) { JNU_ThrowIOExceptionWithLastError(env,"write to interrupt fd failed"); } } 写入一个字节的fakebuf。有朋友问起这个问题,写个注记在此。strace充分利用对了解这些细节很有帮助。 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-10-22
不错。知其然并知其所以然~
|
|
返回顶楼 | |
发表时间:2010-10-26
写的不错,以前看到过类似文章介绍过nio wakeup的工作模式
strace命令用的不多,下次可以研究下了 |
|
返回顶楼 | |
浏览 5334 次