Java - 单例模式
单例模式
是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,
应用该模式的类一个类只有一个实例。即一个类只有一个对象实例
单例定义
数学与逻辑学中,singleton定义为“有且仅有一个元素的集合”。
单例模式最初的定义出现于《设计模式》(艾迪生维斯理, 1994):“保证一个类仅有一个实例,并提供一个访问它的全局访问点。”
Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”
* 单例模式:确保某一个类,能产生一个实例
*
* 设计思路:
* 1, 将构造函数私有化,确保类外部不能使用new关键字自行创建对象
* 2, 在类的内部实例化一个对象,并通过静态方法返回
例:一个普通的单例类
class Singleton{
private Singleton(){
System.out.println("单例模式");
}
实现单例模式的方法:饿汉式单例、懒汉式单例、双重加锁的懒汉式单例模式、使用synchronized 同步类、使用静态内部类实现单例
注:由于实现单例的方法有很多,这也使得他们懂得优缺点也存在差异,这就需要我们在编写过程中选择合适的方法来运用的项目中去
接下来我们分别看一下实现代码:
饿汉式单例:
private static Singleton sing = new Singleton();
public static Singleton getIns(){
return sing;
}
缺点:在类一加载时,就实例化对象,提前占用系统资源
//对第一行static的一些解释
//java允许我们在一个类里面定义静态类。比如内部类(nested class)。
//把nested class封闭起来的类叫外部类。
//在java中,我们不能用static修饰顶级类(top level class)。
//只有内部类可以为static。
懒汉式单例:
private static Singleton sing = null;
public static Singleton getIns(){
if (sing==null) {
sing = new Singleton();
}
return sing;
}
优点:解决了懒汉式提前占用系统资源的问题
使用synchronized 同步类
private static Singleton sing = null;
public static synchronized Singleton getIns(){
if (sing==null) {
sing = new Singleton();
}
return sing;
}
synchronized :将一个方法或者代码块进行加锁,同一个时间只允许一个线程访问,对方法进行加锁,确保懒汉式单例,可以线程安全
双重加锁的懒汉模式:只有第一次sing为null的时候才进行线程锁
private static Singleton sing = null;
public static Singleton getIns(){
if(sing==null){
synchronized(Singleton.class){
if (sing==null) {
sing = new Singleton();
}
}
}
return sing;
}
当后续sing不为null时就无需线城锁,可以允许多个线程同时拿走sing
//这个模式将同步内容下放到if内部,提高了执行的效率,不必每次获取对象时都进行同步,只有第一次才同步,创建了以后就没必要了。
//这种模式中双重判断加同步的方式,比第一个例子中的效率大大提升,因为如果单层if判断,在服务器允许的情况下,
//假设有一百个线程,耗费的时间为100*(同步判断时间+if判断时间),而如果双重if判断,100的线程可以同时if判断,理论消耗的时间只有一个if判断的时间。
//所以如果面对高并发的情况,而且采用的是懒汉模式,最好的选择就是双重判断加同步的方式。
静态内部类实现单例:
private static class Singleton1{
private static Singleton sing = new Singleton();
}
public static Singleton getIns(){
return Singleton1.sing;
}
优点:解决了饿汉式提前占用资源的问题,解决了懒汉式线程不安全的问题