Java高级技术第五章——高并发之常用的线程安全的单例模式

前言

前言点击此处查看:
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; inew Thread(()->{

                                Singleton.getSingle();

                        });

                }
                Arrays.asList(ths).forEach(o->o.start());
                System.out.println("over");
        }
}

输出结果是

……
199
single
over

可以看到,在最后的一次循环当中才真正实例化这个单例模式的类。这样,在开启多个线程的new对象的时候,也确保这个类中只有一个对象,同时,也实现了懒加载。

你可能感兴趣的:(JAVA高级编程系列)