五种单例模式:

package singleton;


/***
* 设计模式:一种套路,一种经验总结.
* 单例模式:
* 1)属于一种创建型模式(与对象创建相关)
* 2)是为了保证类的对象在内存中的全局唯一性,给定
* 的一种设计规则.
* 单例模式应用场景:
* 1)池对象的应用(例如字符串池)
* 2)资源访问对象
* 单例模式应用的目的:(减少对象对资源占用)
* 单例模式的具体实现思路?
* 规则:
* 1)类的外部不允许直接构建此类对象
* 2)类的外部只能通过静态方法访问此对象
* 实现:
* 1)构造方法私有化
* 2)在类的内部构建对象
* 3)定义一个静态方法,通过这个方法直接返回此对象

单例模式有以下特点:
  1、单例类只能有一个实例。
  2、单例类必须自己创建自己的唯一实例。
  3、单例类必须给所有其他对象提供这一实例。
  单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。

*/
//单例设计方案1
class Singleton01{
private Singleton01(){}
private static Singleton01 instance;
public static Singleton01 getInstance(){
if(instance==null){
instance=new Singleton01();
}
return instance;
}
}
//以上单例设计可能存在什么问题?(线程安全问题)

Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。

(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)

但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全,如果你第一次接触单例模式,对线程安全不是很了解,可以先跳过下面这三小条,去看饿汉式单例,等看完后面再回头考虑线程安全的问题:


//单例设计方案2(线程安全单例)
class Singleton02{
private Singleton02(){}
private static Singleton02 instance;
public static synchronized Singleton02 getInstance(){
if(instance==null){
instance=new Singleton02();
}
return instance;
}
}
//以上单例设计存在什么问题吗?(性能问题)
//单例设计方案3(线程安全+效率)
class Singleton03{//大对象,稀少用
private Singleton03(){}
private static Singleton03 instance;
public static Singleton03 getInstance(){
if(instance==null){
synchronized (Singleton03.class) {
if(instance==null){
instance=new Singleton03();
}
}
}
return instance;
}
}
//以上设计适合对instance对象的频繁访问吗?不适合

//单例设计方案四(小对象频繁用)
class Singleton04{
//private int[] array=new int[1024];
private Singleton04(){}
/**类加载时创建*/
private static final Singleton04 instance=
new Singleton04();
/**此方法中因为没有阻塞问题所以适合频繁访问*/
public static Singleton04 getInstance() {
return instance;
}
//public static void display(){}
//public void show(){}
}
//请问以上设计存在什么问题吗?(假如对象比较大,
//类加载时就创建了此对象,假如不使用,就可能长时间占用资源)
//单例设计方案五(采用延迟加载策略优化设计方案四)
class Singleton05{
private Singleton05(){}
static class Lazy{//类何时被加载?
public static final Singleton05
instance=new Singleton05();
}
public static Singleton05 getInstance(){
//何时需要何时加载
return Lazy.instance;
}
//请问访问Singleton05类的这个方法时候会加载Lazy吗?

//public static void display(){}//不会,这是静态方法,加载类时不会加载Lazy
//请问访问Singleton05类的show方法时是否需要加载Lazy?
//public void show(){}//会,这是实例方法,创建实例对象时会加载Lazy
}
//---------------------------------------------

public class TestSingleton {

public static void main(String[] args) {

for(int i=0;i<5;i++){
new Thread(){
public void run() {
System.out.println(
Singleton01.getInstance()
);
};
}.start();
}

}
}

posted @ 2018-03-22 08:11  小黑妹007  阅读(137)  评论(0编辑  收藏  举报