今天在练习用nio写一个聊天室时,突然想到了一个问题,我们在客户端和服务端都使用Selector,那这个Selector是否是同一个呢,它是怎么创建的呢,所以我自己看了看源码。
Selector类里有静态方法
public static Selector open() throws IOException {
return SelectorProvider.provider().openSelector();
}
它是应用了 SelectorProvider类的provider()方法
SelectorProvider是一个抽象类 provider()方法如下
public static SelectorProvider provider() {
synchronized (lock) {//这是一个类锁 private static final Object lock = //new Object(); 防止多线程下干扰
if (provider != null)//private static SelectorProvider provider = null;
return provider;//这是一个单例模式
return AccessController.doPrivileged(//检查了权限
new PrivilegedAction() {
public SelectorProvider run() {
if (loadProviderFromProperty())//从配置文件中读取见下文
return provider;
if (loadProviderAsService())//见下面分析
return provider;
provider = sun.nio.ch.DefaultSelectorProvider.create();
//返回了系统默认的SelectorProvider
return provider;
}
});
}
}
private static boolean loadProviderFromProperty() {
String cn = System.getProperty(“java.nio.channels.spi.SelectorProvider”);
if (cn == null)
return false;
try {
Class<?> c = Class.forName(cn, true,
ClassLoader.getSystemClassLoader());
provider = (SelectorProvider)c.newInstance();
return true;
} catch (ClassNotFoundException x) {
throw new ServiceConfigurationError(null, x);
} catch (IllegalAccessException x) {
throw new ServiceConfigurationError(null, x);
} catch (InstantiationException x) {
throw new ServiceConfigurationError(null, x);
} catch (SecurityException x) {
throw new ServiceConfigurationError(null, x);
}
}
获取了SelectorProvider的全类名 然后拿到系统的类文件加载器通过反射,拿到实例。
private static boolean loadProviderAsService() {
ServiceLoader<SelectorProvider> sl =
ServiceLoader.load(SelectorProvider.class,
ClassLoader.getSystemClassLoader());
Iterator<SelectorProvider> i = sl.iterator();
for (;;) {
try {
if (!i.hasNext())
return false;
provider = i.next();
return true;
} catch (ServiceConfigurationError sce) {
if (sce.getCause() instanceof SecurityException) {
// Ignore the security exception, try the next provider
continue;
}
throw sce;
}
}
}
从服务加在器中加在是否有服务中已经安装了Provider的jar包,如果有则返回,没有则抛异常
由此可见Selector由系统提供的SelectorProvider获得,与你所使用的系统有关,Provider是一个单例模式,所以只有一个provider,获得一个相同的Selector