版权信息:
原文地址:http://www.blogjava.net/killme2008/archive/2010/10/22/335861.html
原文作者:dennis.zane
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();
}
}
使用strace调用,只关心write的系统调用
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
有的同学说了,怎么证明这个write是wakeup方法调用的,而不是其他方法呢,这个很好证明,我们多调用几次:
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
果然是3次write的系统调用,都是写入一个字节,如果我们去掉selectNow,那么三次wakeup还是等于一次:
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
wakeup方法的API说明没有欺骗我们。wakeup方法的API还告诉我们,如果当前Selector没有阻塞在select方法上,那么本次wakeup调用会在下一次select阻塞的时候生效,这个道理很简单,wakeup方法写入一个字节,下次poll等待的时候立即发现可读并返回,因此不会阻塞。
具体到源码级别,在linux平台上的wakeup方法其实调用了pipe创建了管道,wakeup调用了EPollArrayWrapper的interrupt方法:
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充分利用对了解这些细节很有帮助。
分享到:
相关推荐
基于jQuery Selector.js插件实现的联动下拉框表单美化效果源码.zip
Java-NIO之Selector.doc
Android文字颜色背景触摸点击反馈色之selector.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
Android-Ultra-Photo-Selector.zip,太多无法一一验证是否可用,程序如果跑不起来需要自调,部分代码功能进行参考学习。
前端开源库-matches-selector.zip
【IT十八掌徐培成】Java基础第27天-03.NIO-Selector.zip
jquery.selector-px.js 在微信端实现苹果的下拉框的选取
selector.java
一个可以用代号处理控件的阴影效果,以及用代号在TextView、EditText、Button等控件设置selector.zip
资源来自pypi官网。 资源全名:selector-0.8.10.tar.gz
selector.zip 百分比 渐变色 圆圈分析图
SMC 空气组合原件选型软件
Contact Selector介绍: 打开设备的联系人列表,选择某个联系人,获取联系人信息,包括头像、姓名等等。 测试环境: Eclipse 4.2, Android 3.0 以上。 注意:测试环境并不代表适用环境。
Android 选择多张相册照片 可以设置选择日期 是否显示拍照功能 选择相片张数等功能 Android 选择多张相册照片 可以设置选择日期 是否显示拍照功能 选择相片张数等功能
Java_NIO类库Selector机制解析 ,很详细 有兴趣可以下载看看。
前端大厂最新面试题-selector
选择日期
#过滤式特征选择 #根据方差进行选择,方差越小,代表该属性识别能力很差,可以剔除 from sklearn.feature_selection import VarianceThreshold x=[[100,1,2,3], [100,4,5,6], ...selector.get_support(True)
选择器.js 使用 javascript 构建 CSS 选择器和 DOM 遍历器。 在“src”文件夹中查找您需要编写的名为 selector.js 的文件(去图!) “spec”文件夹包含我们将使用的测试文件