概念理解
单例模式,最常见的就是饥饿模式,和懒汉模式,一个直接实例化对象,一个在调用方法时进行实例化对象。在多线程模式中,考虑到性能和线程安全问题,我们一般选择下面两种比较经典的单例模式,在性能提高的同时,又保证了线程安全。
案例
在这里讲两种常用的模式
1、Double Check Locking 双检查锁机制
public class DubbleSingleton {
private static DubbleSingleton ds;
public static DubbleSingleton getDs(){
if(ds == null){//第一次判断
try {
//模拟初始化对象的准备时间...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//锁定当前类 DubbleSingleton 不能有另外一个线程创建DubbleSingleton这个实例
synchronized (DubbleSingleton.class) {
//双重判断 没有这个hashCode就会不一样 原因 :不能重新创建DubbleSingleton实例 重新创建hashCode将不一样 只有再次判断才能保持是单例的
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
}
public static void main(String[] args) {
//单例的 三个线程hashCode是一样的 否则不是单例的
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
打印结果
37026807
37026807
37026807
从运行结果来看,该中方法保证了多线程并发下的线程安全性。
在同步代码块中使用二次检查,以保证其不被重复实例化。这种实现方式既保证了其高效性,也保证了其线程安全性。
2、static inner class(静态内部类)
静态代码块中的代码在使用类的时候就已经执行了,所以可以应用静态代码块的这个特性的实现单例设计模式。
public class Singletion {
//单例 线程安全的
private static class InnerSingletion {
private static Singletion single = new Singletion();
}
public static Singletion getInstance(){
return InnerSingletion.single;
}
public static void main(String[] args) {
//单例的 三个线程hashCode是一样的 否则不是单例的
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Singletion.getInstance().hashCode());
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Singletion.getInstance().hashCode());
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Singletion.getInstance().hashCode());
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}
打印结果
191824015
191824015
191824015
从运行结果看,单例的线程安全性得到了保证。
源代码:https://github.com/hfbin/Thread_Socket/tree/master/Thread/conn011