Java NIO中的选择器Selector对象,依赖操作系统内核的系统调用poll和epoll。
1. 选择器Selector的open()函数
当调用Selector.open()时,选择器通过专门的工厂SelectorProvider来创建Selector的实现,SelectorProvider屏蔽了不同操作系统及版本创建实现的差异性。具体实现代码如下:
java.nio.channels.Selector
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
2. provider()函数提供具体的provider对象
因为SelectorProvider本身为一个抽象类,通过调用provider()提供对应的Provider实现,如PollSelectorProvider、EPollSelectorProvider
java.nio.channels.spi.SelectorProvider
public static SelectorProvider provider() {
synchronized (lock) {
if (provider != null)
return provider;
return (SelectorProvider)AccessController
.doPrivileged(new PrivilegedAction() {
public Object run() {
if (loadProviderFromProperty())
return provider;
if (loadProviderAsService())
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
return provider;
}
});
}
}
3. DefaultSelectorProvider对象,是默认的selector提供器
默认的Provider实现即为DefaultSelectorProvider,通过调用create(),得到具体的SelectorProvider,这是linux操作系统下的DefaultSelectorProvider的实现。
可以看到,如果内核版本>=2.6则,具体的SelectorProvider为EPollSelectorProvider,否则为默认的PollSelectorProvider
sun.nio.ch.DefaultSelectorProvider
public static SelectorProvider create() {
PrivilegedAction pa = new GetPropertyAction("os.name");
String osname = (String) AccessController.doPrivileged(pa);
if ("SunOS".equals(osname)) {
return new sun.nio.ch.DevPollSelectorProvider();
}
// use EPollSelectorProvider for Linux kernels >= 2.6
if ("Linux".equals(osname)) {
pa = new GetPropertyAction("os.version");
String osversion = (String) AccessController.doPrivileged(pa);
String[] vers = osversion.split("\\.", 0);
if (vers.length >= 2) {
try {
int major = Integer.parseInt(vers[0]);
int minor = Integer.parseInt(vers[1]);
if (major > 2 || (major == 2 && minor >= 6)) {
return new sun.nio.ch.EPollSelectorProvider();
}
} catch (NumberFormatException x) {
// format not recognized
}
}
}
return new sun.nio.ch.PollSelectorProvider();
}
EPollSelectorProvider提供的Selector与内核epoll有关的:
public AbstractSelector openSelector() throws IOException {
return new EPollSelectorImpl(this);
}
PollSelectorProvider提供的Selector肯定是与poll有关的:
public AbstractSelector openSelector() throws IOException {
return new PollSelectorImpl(this);
}