前言
前言点击此处查看:
http://blog.csdn.net/wang7807564/article/details/79113195
线程安全的单例模式
单例模式就是说系统中对于某个类只能有一个实例,多线程下面单例模式的线程安全问题是一个典型应用场景。一般常用单例模式做资源控制与调配,例如使用单例模式做一个线程池,数据库链接池等等。
饿汉模式
饿汉模式是在该类被加载的时候,就已经实例化对象了,生成的对象是static的,因此一直被JVM加载在内存中,相当于拿“空间换时间”,因此是线程安全的。
//饿汉式单例模式
public class Singleton {
//设立静态变量,直接创建实例
private static Singleton my = new Singleton();
private Singleton(){
//私有化构造函数
System.out.println("-->饿汉式单例模式开始调用构造函数");
}
//开放一个公有方法,判断是否已经存在实例
public static Singleton getInstance(){
System.out.println("-->饿汉式单例模式开始调用公有方法返回实例");
return my;
}
}
双重锁的懒汉模式
懒汉模式也就是懒加载,只有在该单例模式的对象被用的时候才会实例化,如果不用就不去实例化,相当于“拿时间换空间”。
由于懒汉模式不是线程安全的,但是加一个synchronized的话效率又太差,故而往往使用双重锁:
public class Singleton {
private static Singleton singleton;
private Singleton(){
}
public static Singleton getInstance(){
if(singleton == null){
synchronized(Singleton.class){
if(singleton == null){
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类
在下面的方式中,既不用加锁,也能实现懒加载:
public class Singleton{
private Singleton(){
System.out.println("single");
}
private static class Inner{
private static Singleton s=new Singleton();
}
public static Singleton getSingle(){
return Inner.s;
}
}
在一个名为Test的测试类中写入测试代码:
import java.util.Arrays;
class Test{
public static void main(String[] args) {
Thread[] ths = new Thread[200];
for(int i=0; i<ths.length; i++) {
System.out.println(i);
ths[i] = new Thread(()->{
Singleton.getSingle();
});
}
Arrays.asList(ths).forEach(o->o.start());
System.out.println("over");
}
}
输出结果是
……
199
single
over
可以看到,在最后的一次循环当中才真正实例化这个单例模式的类。这样,在开启多个线程的new对象的时候,也确保这个类中只有一个对象,同时,也实现了懒加载。