一、单例模式(Singleton Pattern)
1、定义
- 单例模式(Singleton Pattern)是指确保一个类在任何情况下都绝对只有一个实例,并提供一个全局访问点。
- 隐藏起所有的构造方法
- 属于创建型模式。
2、单例模式的适用场景
确保任何情况下都绝对只有一个实例
ServletContext,ServletConfig,ApplicationContext,DBPool
3、单例模式的常见写法
- 饿汉式单例
- 懒汉式单例
- 注册式单例
- ThreadLocal单例
1)饿汉式单例
- 优点:执行效率高,性能高,没有任何锁;
- 缺点:某些情况下,可能会造成内存浪费;
- 示例代码
package pattern.factory.singleton.hungry;
/**
* 优点:执行效率高,性能高,没有任何的锁
* 缺点:
* 1、某些情况下,内存浪费;加载时,即初始化类
* 2、存在多个类暴增情况,内存浪费;
*/
public class HungrySingleton {
//以下写法与这个无差别,都是加载时,初始化类;private static final HungrySingleton hungrySingleton = new HungrySingleton();
private static final HungrySingleton hungrySingleton;
static {
hungrySingleton = new HungrySingleton();
}
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
2)懒汉式单例
- 优点:使用时才创建,节省内存
- 缺点:
* 无synchronize:线程不安全;存量多个线程,调用instance方法; * 用synchronized避免线程不安全; 所有的资源只能有一个线程使用,一个线程使用时,其他线程处于监听状态,队列,会造成性能瓶颈
- 示例代码
1、特点:使用synchronize避免线程不安全,导致所有的资源只能一个线程使用,资源占用时,其他线程处于监听状态,队列中,会造成性能瓶颈。
package pattern.factory.singleton.lazy;
/**
* 优点:节省内存;
* 缺点:
* 无synchronize:线程不安全;存量多个线程,调用instance方法;
* 用synchronized避免线程不安全】
* 所有的资源只能有一个线程使用,一个线程使用时,其他线程处于监听状态,队列,会造成性能瓶颈
*/
public class LazySimpleSingleton {
private static LazySimpleSingleton instance;
private LazySimpleSingleton(){
}
public synchronized static LazySimpleSingleton getInstance(){
if(null == instance){
instance = new LazySimpleSingleton();
}
return instance;
}
}
package pattern.factory.singleton.test;
import pattern.factory.singleton.lazy.LazySimpleSingleton;
public class ExectorThread implements Runnable{
@Override
public void run() {
LazySimpleSingleton instance = LazySimpleSingleton.getInstance();
System.out.printf("\n"+Thread.currentThread().getName()+":"+instance);
}
}
package pattern.factory.singleton.test;
public class LazySimpleSingletonTest {
public static void main(String[] args) {
Thread t1 = new Thread(new ExectorThread());
Thread t2 = new Thread(new ExectorThread());
t1.start();
t2.start();
System.out.printf("End");
}
}
2、解决性能问题
多重判断,首先检查是否堵塞,后面判断是否创建实例。
优点:性能提高,线程安全;
缺点:可读性低
package pattern.factory.singleton.lazy;
/**
* 优点:性能高了,线程安全了。
* 缺点:可读性低,不够优雅。
*/
public class LazyDoubleCheckSingleton {
private volatile static LazyDoubleCheckSingleton instance;
private LazyDoubleCheckSingleton(){
}
public static LazyDoubleCheckSingleton getInstance(){
//检查是否堵塞
if(null==instance){
synchronized (LazyDoubleCheckSingleton.class){
//检查是否创建实例
if(null==instance){
instance = new LazyDoubleCheckSingleton();
}
}
}
return instance;
}
}