先說結論:
靜態內部類實現單例模式,是藉助了類加載器加載類的特性實現的,類加載器在加載類時使用了synchronized關鍵字.
單例模式代碼:
public class SingletonDemo {
public static void main(String[] args) {
SingletonDemo sd1 = getInstance();
SingletonDemo sd2 = getInstance();
System.out.println(sd1.equals(sd2));
}
private SingletonDemo(){};
private static class SingletonHolder{
private static SingletonDemo INSTANCE = new SingletonDemo();
}
public static SingletonDemo getInstance(){
return SingletonHolder.INSTANCE;
}
}
輸出爲:
true
首次執行getInstance()方法,調用SingletonHolder中的靜態屬性INSTANCE時,觸發SingletonHolder類的加載,而new SingletonDemo()也會被執行,且只被執行一次.
在多線程環境下是如何實現同步的呢?這就要看ClassLoader類的源碼了:
public Class<?> loadClass(String name) throws ClassNotFoundException {
return loadClass(name, false);
}
經過調試,可以確定的是,程序先進入了上面這個方法.但是點擊F7進入的卻不是下面這個方法:
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
synchronized (getClassLoadingLock(name)) {
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
long t0 = System.nanoTime();
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
long t1 = System.nanoTime();
c = findClass(name);
// this is the defining class loader; record the stats
PerfCounter.getParentDelegationTime().addTime(t1 - t0);
PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
PerfCounter.getFindClasses().increment();
}
}
if (resolve) {
resolveClass(c);
}
return c;
}
}
進入的是ClassLoaders.AppClassLoader類中的loadClass()方法:
@Override
protected Class<?> loadClass(String cn, boolean resolve)
throws ClassNotFoundException
{
// for compatibility reasons, say where restricted package list has
// been updated to list API packages in the unnamed module.
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
int i = cn.lastIndexOf('.');
if (i != -1) {
sm.checkPackageAccess(cn.substring(0, i));
}
}
return super.loadClass(cn, resolve);
}
執行super.loadClass(),進入了BuiltinClassLoader類中的loadClass()方法:
@Override
protected Class<?> loadClass(String cn, boolean resolve)
throws ClassNotFoundException
{
Class<?> c = loadClassOrNull(cn, resolve);
if (c == null)
throw new ClassNotFoundException(cn);
return c;
}
執行loadClassOrNull()方法,然後進入同一個類中的loadClassOrNull()方法:
protected Class<?> loadClassOrNull(String cn, boolean resolve) {
synchronized (getClassLoadingLock(cn)) {
// check if already loaded
Class<?> c = findLoadedClass(cn);
if (c == null) {
// find the candidate module for this class
LoadedModule loadedModule = findLoadedModule(cn);
if (loadedModule != null) {
// package is in a module
BuiltinClassLoader loader = loadedModule.loader();
if (loader == this) {
if (VM.isModuleSystemInited()) {
c = findClassInModuleOrNull(loadedModule, cn);
}
} else {
// delegate to the other loader
c = loader.loadClassOrNull(cn);
}
} else {
// check parent
if (parent != null) {
c = parent.loadClassOrNull(cn);
}
// check class path
if (c == null && hasClassPath() && VM.isModuleSystemInited()) {
c = findClassOnClassPathOrNull(cn);
}
}
}
if (resolve && c != null)
resolveClass(c);
return c;
}
}
終於出現了,synchronized關鍵字!
調用鏈很長,但是都是在synchronized中了,就不繼續往下走了.