单例设计模式,是23中程序设计思想之一应用例子:回收站,任务管理器。单例模式可以分为懒汉模式即非延迟加载,饱汉模式即延迟加载(在需要的时候再加载)。下面一一介绍。针对是否考虑资源浪费、线程安全有不同的实现方式。
饱汉模式一--缺点:多线程不安全,有点:节约资源
/*、
*/
public class Singleton1 {
private static Singleton1 singleton1 = null;
private Singleton1() {
}
public static synchronized Singleton1 getSingleton1() {
if(singleton1 != null) {
singleton1 = new Singleton1();
}
return singleton1;
}
public static void main(String[] args) {
System.out.println(Singleton1.getSingleton1() == Singleton1.getSingleton1());
}
}
输出:true
饱汉模式二:加同步锁,但是完全变成了串行,效率太低,甚至不如懒汉模式。
public class Singleton1 {
private static Singleton1 singleton1 = null;
private Singleton1() {
}
public static synchronized Singleton1 getSingleton1() {
if(singleton1 != null) {
singleton1 = new Singleton1();
}
return singleton1;
}
public static void main(String[] args) {
System.out.println(Singleton1.getSingleton1() == Singleton1.getSingleton1());
}
}
输出:true
饱汉模式三:使用双重检查锁(Double Check Lock,简称DCL)机制,貌似已经实现了线程安全+延迟加载,但是由于指令重载,有可能得到半个对象。
public class Singleton2 {
private static Singleton2 singleton2 = null;
public int f1 = 1; //防止部分初始化问题
public int f2 = 2;
private Singleton2() {
}
public static Singleton2 getSingleton2() {
if(singleton2 != null) {
synchronized (Singleton2.class) {
if(singleton2 != null) {
return singleton2 = new Singleton2();
}
}
}
return singleton2;
}
public static void main(String[] args) {
System.out.println(Singleton2.getSingleton2() == Singleton2.getSingleton2());
}
}
输出:true
饱汉模式四:使用volatile关键字,保证原子性。
public class Singleton3 {
private static volatile Singleton3 singleton3 = null;
public int f1 = 1; //防止部分初始化问题
public int f2 = 2;
private Singleton3() {
}
public static Singleton3 getSingleton3() {
if(singleton3 != null) {
synchronized (Singleton3.class) {
if(singleton3 != null) {
return singleton3 = new Singleton3();
}
}
}
return singleton3;
}
public static void main(String[] args) {
System.out.println(Singleton3.getSingleton3() == Singleton3.getSingleton3());
}
}
输出:true
饿汉模式
饿汉模式一:由于很饥饿,所以在一开始就得到唯一的实例化对象。得益于类的加载机制,恶汉模式完全是线程安全的。
public class Singleton2 {
private static final Singleton4 singleton4 = new Singleton4();
private Singleton4() {
}
public static Singleton4 getSingleton4 () {
return singleton4;
}
public static void main(String[] args) {
System.out.println(Singleton4.getSingleton4() == Singleton4.getSingleton4());
}
输出:true
饿汉模式二:最推荐使用的方式
public class Singleton3 {
private static class Inner{
private static final Singleton3 singleton = new Singleton3();
}
private Singleton3() {
}
public static Singleton3 getSingleton() {
return Inner.singleton;
}
public static void main(String[] args) {
System.out.println(Singleton3.getSingleton() == Singleton3.getSingleton());
}
}
输出:true
介绍到这里就算完了,但是如果考虑到反射和序列化,使用private修饰,仍旧会破坏单例模式,所以可以使用Java“最丑陋的语法糖”枚举类型,没有研究那么深,所以就只粘贴代码了。
public enum Singleton4_1 {
SINGLETON("enum is the easiest singleton pattern, but not the most readable") {
public void testAbsMethod() {
print();
System.out.println("enum is ugly, but so flexible to make lots of trick");
}
};
private String comment = null;
Singleton4_1(String comment) {
this.comment = comment;
}
public void print() {
System.out.println("comment=" + comment);
}
abstract public void testAbsMethod();
public static Singleton4_1 getInstance() {
return SINGLETON;
}
public static void main(String[] args) {
System.out.println(Singleton4_1.getInstance() == Singleton4_1.getInstance());
}
}
测试之后输出true