单例设计模式:
所谓单例模式,就是在程序中任何位置调用new方法创建单例的类,永远只会有一个对象被实例化产生,具体不周如下:
(1)将该单例模式的类的构造方法私有化(采用private修饰)。
(2)在其内部产生该类的实例化对象,并将其封装成private static类型。
(3)定义一个静态方法,返回该类实例。
示例代码如下:
class Singleton {
private static Singleton instance = new Singleton();// 在内部产生本类的实例化对象
public static Singleton getInstance() { // 通过静态方法返回instance对象
return instance;
}
private Singleton() { // 将构造方法封装为私有化 }
public void print() {
System.out.println("Hello World!!!");
}
}
public class SingletonDemo {
public static void main(String args[]) {
Singleton s1 = null; // 声明对象
Singleton s2 = null; // 声明对象
Singleton s3 = null; // 声明对象
s1 = Singleton.getInstance(); // 取得实例化对象
s2 = Singleton.getInstance(); // 取得实例化对象
s3 = Singleton.getInstance(); // 取得实例化对象
s1.print(); // 调用方法
s2.print(); // 调用方法
s3.print(); // 调用方法
}
}
由上面的代码,可以大致看出单例设计模式的基本模型了。
单例模式主要由两种形式,俗称:饿汉式及饱汉式。
(1)饿汉式:
/**
* 单例模式的实现:饿汉式,线程安全 但效率比较低
*/
public class SingletonTest {
private SingletonTest() { }
private static final SingletonTest instance = new SingletonTest();
public static SingletonTest getInstancei() {
return instance;
}
}
(2)饱汉式:
/**
* 单例模式的实现:饱汉式,非线程安全
*/
public class SingletonTest {
private SingletonTest() { }
private static SingletonTest instance;
public static SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
很明显,饱汉式使用时,是非线程不安全的,因为当多个线程中同时调用获取单例实例时,可能导致new SingletonTest()会被多次调用,这样就不是所谓的单例了。
因此在饱汉式的基础上,还需完善一下,才能实现完美的单例模式。
线程安全,主要采取的方法就是避免多个线程同时访问“关键”代码,给关键代码加个同步锁。同步又有两种方式,方式一:将该方法加个“同步(synchronized)”关键字,使其成为同步方法,但是这样做的效率相比方式二,效率是比较低的,原因就是整个方法都成了“同步”的,而不是关键代码“同步”。方式二:关键代码处加同步关键字。
方式一:
/**
* 线程安全,但是效率非常低
*/
public class SingletonTest {
private SingletonTest() {}
private static SingletonTest instance;
public static synchronized SingletonTest getInstance() {
if (instance == null)
instance = new SingletonTest();
return instance;
}
}
方式二:
/**
* 线程安全 并且效率高
*/
public class SingletonTest {
private static SingletonTest instance;
private SingletonTest() {}
public static SingletonTest getIstance() {
if (instance == null) {
synchronized (SingletonTest.class) {//同步中的对象保证唯一即可,这个属于同步的使用方法。
if (instance == null) {
instance = new SingletonTest();
}
}
}
return instance;
}
}
所以通常都是采用“双重判空+同步锁”的方式,这样保证了“同步”的高效执行
此博客最先发表于:xuqingsong.farbox.com