Java设计模式(一)单例模式
1、基本介绍
-
单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建。这个类提供了一种访问其唯一的对象的方式,可以直接访问,不需要实例化该类的对象。在整个程序的运行过程中,所有该类的引用都指向同一个实例。
-
-
整个程序运行过程中只有一个实例。
-
类必须在内部创建自己的实例。
-
该类必须提供一个公共方法供其它类获取这个实例。
-
-
好处:
-
防止一个类被频繁的创建和销毁,降低了系统的资源消耗,因为只有一个实例。
-
避免对资源的多重占用。
-
2、应用场景
-
要求生产唯一序列号。
-
WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。
-
创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。
二 、单例模式的七种实现
1、饿汉式-静态常量
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2.本类内部声明对象并初始化
private final static Singleton instance = new Singleton();
//3.对外提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
-
饿汉式-静态常量
-
构造器私有;
-
内部声明静态常量并初始化;
-
提供public方法获取实例。
-
-
优点:
-
写法简单;
-
类加载时完成实例化,线程安全。
-
-
缺点:
-
没有实现懒加载,如果没有用到该类,则会造成资源浪费。
-
2、饿汉式-静态代码块
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2.本类内部声明对象
private static Singleton instance;
static {
//静态代码块中对象实例化
instance = new Singleton();
}
//3.对外提供一个公有的静态方法,返回实例对象
public static Singleton getInstance(){
return instance;
}
}
-
饿汉式-静态代码块
-
构造器私有;
-
内部声明静态常量;
-
通过静态代码块初始化
-
提供public方法获取实例。
-
-
优点:
-
写法简单;
-
类加载时完成实例化,线程安全。
-
-
缺点:
-
没有实现懒加载,如果没有用到该类,则会造成资源浪费。
-
3、懒汉式-线程不安全
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2.本类内部声明对象
private static Singleton instance;
//3.对外提供一个公有的静态方法,第一次使用时实例化对象
public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
-
懒汉式-线程不安全
-
构造器私有;
-
内部创建静态常量;
-
第一次使用时实例化对象。
-
-
优点:
-
使用时加载,避免资源浪费,只能在单线程使用。
-
-
缺点:
-
如果多个线程同时进入if判空,则有可能创建多个实例,线程不安全。
-
4、懒汉式-同步关键字(线程安全)
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2.本类内部声明对象
private static Singleton instance;
//3.对外提供一个公有的静态方法,第一次使用时实例化对象,并加入同步关键字
synchronized public static Singleton getInstance(){
if(instance == null){
instance = new Singleton();
}
return instance;
}
}
-
懒汉式-同步关键字(线程安全)
-
构造器私有;
-
内部声明静态常量;
-
第一次访问实例化对象;
-
加入synchronized同步关键字,每次只有一个线程能进入该方法。
-
-
优点:
-
线程安全;
-
懒加载。
-
-
缺点:
-
效率太低,每次调用getInstance要进行同步,不推荐使用。
-
5、懒汉式-双重检查(线程安全)
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2.本类内部声明对象,使用volatile修改其他线程可立即感知并且防止代码重排序
private static volatile Singleton instance;
//3.对外提供一个公有的静态方法,第一次使用时实例化对象,并加入同步代码块双重检查
public static Singleton getInstance(){
if(instance == null){
{
synchronized (Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
}
return instance;
}
}
-
懒汉式-双重检查
-
构造器私有;
-
内部声明静态常量并标识volatile关键字;
-
第一次访问进行对象实例化,并使用双重检查机制。
-
-
优点:
-
懒加载;
-
线程安全,除了刚开始多个线程可能需要进行同步,后面都不需要进入同步代码块,效率高,推荐使用。
-
-
缺点:
-
无。
-
6、静态内部类
class Singleton{
//1.构造器私有化
private Singleton(){
}
//2静态内部类
private static class SingletonInstance{
private static final Singleton INSTANCE = new Singleton();
}
//3.公共方法获取实例
public static Singleton getInstance(){
return SingletonInstance.INSTANCE;
}
}
-
静态内部类
-
构造器私有;
-
提供静态类;
-
提供公共静态方法返回对象实例。
-
-
优点:
-
JVM在加载外部类时并不会加载内部类,只有显示调用getInstance才会对内部类进行加载,所以提供了懒加载的效果。
-
线程安全,JVM加载类时是单线程的。
-
-
缺点:
-
无。
-
7、枚举
enum Singleton{
//属性
INSTANCE;
}
//获取对象
//Singleton instance = Singleton.INSTANCE;
-
枚举
-
创建枚举类;
-
提供属性。
-
-
优点:
-
实现简单;
-
多线程安全;
-
防止反序列化重新创建对象;
-
这种方式是 Effective Java 作者 Josh Bloch 提倡的方式。
-
-
缺点:
-
无。
-
三、JDK实现单例模式
-
java.lang包下Runtime类

-
使用了第一种饿汉式

浙公网安备 33010602011771号