head first---------单例模式
单例模式:确保一个类只有一个实例,并提供全局访问点。JAVA中实现单例模式需要一个私有的构造器、一个静态实例化类对象的方法、和一个静态的类变量。做到以上三个点,一个单例的模式便被我们设计出来了。确定在资源和性能上的限制,然后小心地选择适当的方案来实现单件,以解决多线程的问题(利用关键字synchronized可以解决多线程访问问题)。
如果不是才用java 2以上版本的话,双重检查加锁(volatile关键字)实现会失效,其中双重加锁是用于解决在getInstance()中减少使用同步,其首先检查是否实例已经创建了,如果未创建,才进行同步。这样一来,只有第一次会同步。
注意:你如果使用多个类加载器,可能导致单间失效而产生多个实例。
以下是单例模式具体实现代码
其中,单例模式又分为饿汉式和懒汉式
package com.clark.singletonpattern;
/**
* 单例模式
* @author Administrator
*
*/
//懒汉式
public class Singleton {
//第一:一个静态的类变量
private static volatile Singleton singleton=null;
//第二:私有的构造器
private Singleton(){
}
//第三:同步的静态实例化类的方法
public static synchronized Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
//=================测试方法===========================
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
//s1和s2对象的toString()方法打印的一样地址,和对象相等
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1==s2);
}
}
//=======================================================
//饿汉式
public class Singleton {
//第一:一个静态的类变量
private static volatile Singleton singleton=new Singleton();
//第二:私有的构造器
private Singleton(){
}
//第三:同步的静态实例化类的方法
public static synchronized Singleton getInstance(){
return singleton;
}
//=================测试方法===========================
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
//s1和s2对象的toString()方法打印的一样地址,和对象相等
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1==s2);
}
}
如果不是才用java 2以上版本的话,双重检查加锁(volatile关键字)实现会失效,其中双重加锁是用于解决在getInstance()中减少使用同步,其首先检查是否实例已经创建了,如果未创建,才进行同步。这样一来,只有第一次会同步。
注意:你如果使用多个类加载器,可能导致单间失效而产生多个实例。
以下是单例模式具体实现代码
其中,单例模式又分为饿汉式和懒汉式
package com.clark.singletonpattern;
/**
* 单例模式
* @author Administrator
*
*/
//懒汉式
public class Singleton {
//第一:一个静态的类变量
private static volatile Singleton singleton=null;
//第二:私有的构造器
private Singleton(){
}
//第三:同步的静态实例化类的方法
public static synchronized Singleton getInstance(){
if(singleton==null){
singleton=new Singleton();
}
return singleton;
}
//=================测试方法===========================
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
//s1和s2对象的toString()方法打印的一样地址,和对象相等
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1==s2);
}
}
//=======================================================
//饿汉式
public class Singleton {
//第一:一个静态的类变量
private static volatile Singleton singleton=new Singleton();
//第二:私有的构造器
private Singleton(){
}
//第三:同步的静态实例化类的方法
public static synchronized Singleton getInstance(){
return singleton;
}
//=================测试方法===========================
public static void main(String[] args) {
Singleton s1=Singleton.getInstance();
Singleton s2=Singleton.getInstance();
//s1和s2对象的toString()方法打印的一样地址,和对象相等
System.out.println(s1.toString());
System.out.println(s2.toString());
System.out.println(s1==s2);
}
}
在这里也稍微谈谈所谓的double-checked(双重检测),首先申明一下懒汉式并没有使用双重检测的技术,而双重检测是C++语言中的常用技巧之一,如果说它对懒汉式的改造,那就是将方法的标示synchronized 去除,然后在方法体中判断if (instance == null)后使用synchronized{},而在synchronized{}中再次对if (instance == null)进行判断,达到双重检测的目的.但是很可惜这个双重检测对JAVA的编译器不成立,因为instance的检测和对他的申明在时间上并没有严格的先后次序,所以编译器可能会先检测再申明而导致崩溃.