1、懒汉模式(线程不安全的)
public class SingletonTest01 {
public static void main(String[] args) {
new Thread(){
public void run(){
System.out.println(MySingleton01.getInstance());
}
}.start();
new Thread(new Runnable(){
public void run() {
System.out.println(MySingleton01.getInstance());
}
}).start();
}
}
//懒汉模式(是线程不安全的),如果多线程处理时,需加synchronized进行处理
class MySingleton01{
//创建一个私有的静态的类(不实例化)
private static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
//创建私有的构造方法
private MySingleton01(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton01 getInstance(){
if(mySingleton01==null){
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
mySingleton01 = new MySingleton01();
return mySingleton01;
}else{
return mySingleton01;
}
}
}
此处mySingleton01用volatile修饰会更好
改为线程安全的:
class MySingleton01{
//创建一个私有的静态的类(不实例化)
private volatile static MySingleton01 mySingleton01=null;//懒得实例化,所以是懒汉
//创建私有的构造方法
private MySingleton01(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton01 getInstance(){
if(mySingleton01==null){//Java 中的双重检查技术(Double-Check)
synchronized (MySingleton01.class) {
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
if(mySingleton01==null){
mySingleton01 = new MySingleton01();
}
}
return mySingleton01;
}else{
return mySingleton01;
}
}
}
2、饿汉模式(线程安全的)
public class SingletonTest02 {
public static void main(String[] args) {
new Thread(){
public void run(){
System.out.println(MySingleton02.getInstance());
}
}.start();
new Thread(new Runnable(){
public void run() {
System.out.println(MySingleton02.getInstance());
}
}).start();
}
}
//饿汉模式(是线程安全的)
class MySingleton02{
//创建一个私有的静态的类(实例化)
private static MySingleton02 mySingleton=new MySingleton02();
//创建私有的构造方法
private MySingleton02(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton02 getInstance(){
return mySingleton;
}
}
3、延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,推荐使用)
public class SingletonTest03 {
public static void main(String[] args) {
new Thread(){
public void run(){
System.out.println(MySingleton03.getInstance());
}
}.start();
new Thread(new Runnable(){
public void run() {
System.out.println(MySingleton03.getInstance());
}
}).start();
}
}
//延迟加载的饿汉模式(线程安全,而且节省资源,类加载时不会实例化对象,只有在调用getInstance方法后,才会实例化对象)
class MySingleton03{
//创建一个私有的静态的内部类,持有对象(实例化)
private static class MySingleton03Holder{
private static MySingleton03 mySingleton=new MySingleton03();
}
//创建私有的构造方法
private MySingleton03(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton03 getInstance(){
return MySingleton03Holder.mySingleton;
}
}
4、枚举类型实现单例(除了不能延迟加载,其它特性都是极好的,是最安全的,是所有写法中唯一一种不能通过反射或反序列化破解单例的写法,推荐使用)
public class SingletonTest04 {
public static void main(String[] args) {
System.out.println(MySingleton04.INSTANCE==MySingleton04.INSTANCE);
MySingleton04 m1 = MySingleton04.INSTANCE;
MySingleton04 m2 = MySingleton04.INSTANCE;
m1.say();
m1.say();
System.out.println(m2.getI());
}
}
enum MySingleton04{//枚举类型
INSTANCE;
private int i=0;
public void say(){
System.out.println("Hello World !!!");
i++;
}
public int getI() {
return i;
}
}
5、通过反射的方式破解单例模式
public class SingletonTest05 {
public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
System.out.println(MySingleton05.getInstance());
System.out.println(MySingleton05.getInstance());
//通过反射的方式直接调用私有构造器
Class clazz =(Class) Class.forName("com.primeton.singleton.MySingleton05");
Constructor c =clazz.getDeclaredConstructor(null);
c.setAccessible(true);
MySingleton05 mySingleton1 = c.newInstance(null);
MySingleton05 mySingleton2 = c.newInstance(null);
System.out.println(mySingleton1);
System.out.println(mySingleton2);
}
}
class MySingleton05{
//创建一个私有的静态的类(实例化)
private static class MySingleton03Holder{
private static MySingleton05 mySingleton=new MySingleton05();
}
//创建私有的构造方法
private MySingleton05(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton05 getInstance(){
return MySingleton03Holder.mySingleton;
}
public static void say(){
System.out.println("Hello World !!!");
}
}
结果:
com.primeton.singleton.MySingleton05@1cc2ea3f
com.primeton.singleton.MySingleton05@1cc2ea3f
com.primeton.singleton.MySingleton05@40a0dcd9
com.primeton.singleton.MySingleton05@1034bb5
结论:通过该方式让该单例类产生了多个对象
6、通过序列化与反序列化的方式破解单例模式(被破解的单例需实现了Serializable接口才行)
public class SingletonTest06 {
public static void main(String[] args) throws Exception {
System.out.println(MySingleton05.getInstance());
System.out.println(MySingleton05.getInstance());
//通过序列化与反序列化的方式破解单例模式
ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(new File("D://ceshi.txt")));
oos.writeObject(MySingleton06.getInstance());
oos.flush();
oos.close();
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(new File("D://ceshi.txt")));
MySingleton06 mySingleton1 = (MySingleton06) ois.readObject();
System.out.println(mySingleton1);
}
}
class MySingleton06 implements Serializable{
//创建一个私有的静态的类(实例化)
private static class MySingleton03Holder{
private static MySingleton06 mySingleton=new MySingleton06();
}
//创建私有的构造方法
private MySingleton06(){}
//创建一个开放的实例化方法,供外界获取对象
public static MySingleton06 getInstance(){
return MySingleton03Holder.mySingleton;
}
public static void say(){
System.out.println("Hello World !!!");
}
}
结果:
com.primeton.singleton.MySingleton05@3fbefab0
com.primeton.singleton.MySingleton05@3fbefab0
com.primeton.singleton.MySingleton06@4d546e25
结论:通过该方式让该单例类产生了多个对象