单例主要有两种,一种懒汉,一种饿汉,区别在于懒汉在getInstance的时候,才会去初始化单例,而饿汉在类加载之后就立即进行初始化。可见懒汉节省资源,而饿汉的在于天生的线程安全
1.懒汉式单例
package com.test.pattern; class Singleton { private static Singleton singleton; private Singleton(){ System.out.println("hello I'm singleton "+this.hashCode()); } public static Singleton getSingleton() { if(singleton == null) singleton = new Singleton(); return singleton; } } public class SingletonTest { public static void main(String[] args) { Singleton.getSingleton(); Singleton.getSingleton(); Singleton.getSingleton(); } }
这种单例模式是线程不安全的(但如果将getSingleton方法声明为synchronized即可使之线程安全):
package com.test.pattern; /** * @author wangx * @Date: 2016年8月8日 * @func: 懒汉式单例多线程不安全 * @Copyright: 2016 wangx. All rights reserved. */ public class SingletonMultithread { public static void main(String[] args) { new Thread(new Task()).start(); new Thread(new Task()).start(); } } class Task implements Runnable { @Override public void run() { Singleton.getSingleton(); Singleton.getSingleton(); } }
运行结果:
hello I'm singleton 1025866005 hello I'm singleton 1449742585
2.饿汉式单例
package com.test.pattern; /** * @author wangx * @Date: 2016年8月9日 * @func: 饿汉式单例 * @Copyright: 2016 wangx. All rights reserved. */ class Singleton2 { private static Singleton2 singleton=new Singleton2(); private Singleton2() { System.out.println("I'm singleton "+this.hashCode()); } public static Singleton2 getInstance() { return singleton; } } public class SingletonTest2 { public static void main(String[] args) { new Thread(new Task2()).start(); new Thread(new Task2()).start(); } } class Task2 implements Runnable{ @Override public void run() { Singleton2.getInstance(); } }
终:通过反射机制破坏单例
package com.test.reflection; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; class HelloWorld { public void sayHello() { System.out.println("hello world"); } } class Singleton { private Singleton(){} private static Singleton singleton; public Singleton getSingleton() { if(singleton == null) singleton = new Singleton(); return singleton; } public void sayHello() { System.out.println("hello I'm singleton "+this.hashCode()); } } public class ReflectionTest { public static void main(String[] args) throws NoSuchMethodException, SecurityException, ClassNotFoundException, IllegalAccessException, IllegalArgumentException, InvocationTargetException, InstantiationException { Constructor constructor = Class.forName("com.test.reflection.Singleton").getDeclaredConstructor(); constructor.setAccessible(true); Method sayHello = Class.forName("com.test.reflection.Singleton").getDeclaredMethod("sayHello", null); sayHello.invoke(constructor.newInstance(),null); sayHello.invoke(constructor.newInstance(),null); } }