首页 > 代码库 > 单例模式的各种写法和总结 懒汉式 饿汉式 登记式

单例模式的各种写法和总结 懒汉式 饿汉式 登记式

public class Singleton {//懒汉式单例类
/** 懒汉式单例类。   只在外部对象第一次请求实例的时候才会去创建     优点:第一次调用时才会初始化,避免内存浪费。    缺点:必须加锁synchronized 才能保证单例 */
private static Singleton singleton;    private static final ReentrantLock lock = new ReentrantLock();    private static AtomicInteger count=new AtomicInteger(0);        private Singleton() {        count.incrementAndGet();    }    public static synchronized  Singleton getInstance() {            if (singleton == null) {            lock.lock();            if (singleton == null) { //双重锁定,防止几个线程同时进入,eg:a进入,bc等待,a第一次实例化单例,b得到锁后进入,                                        //此处如不判断,则b也会实例化单例,造成多次实例化。 但是多线程测试中没出现这种情况                singleton = new Singleton();            }            lock.unlock();        }        return singleton;    }    public void show(){        System.out.println(count);    }        public static void main(String[] args) throws InterruptedException {//        Singleton s1 = Singleton.getInstance();//        Singleton s2 = Singleton.getInstance();//        if (s1 == s2)//            System.out.println("euqal");//equal//        else {//            System.out.println("not equal");//        }                ExecutorService service = Executors.newCachedThreadPool();        for(int i=0;i<50;i++){            Thread t =new Thread(new MyThread());            service.execute(t);        }        Thread.sleep(5000);        service.shutdown();    }}class MyThread implements Runnable{    @Override    public void run() {        Singleton s = Singleton.getInstance();        s.show();    }    }

 

饿汉式单例类

public class SingletonHungry {public static void main(String[] args) throws InterruptedException {    ExecutorService service = Executors.newCachedThreadPool();    for(int i=0;i<30;i++){        Thread t =new Thread(new MyThread2());        service.execute(t);    }    Thread.sleep(1000);    service.shutdown();}}/*       饿汉式单例类。    它在类加载时就立即创建对象。       优点:没有加锁,执行效率高。  用户体验上来说,比懒汉式要好。        缺点:类加载时就初始化,浪费内存 */class Singleton2{    private static AtomicInteger count = new AtomicInteger(10);    private static final Singleton2 SINGLETON = new Singleton2();    private Singleton2(){        count.incrementAndGet();    }    public static Singleton2 getInstance(){        return SINGLETON;    }    public void show() {        System.out.println(count);    }}class MyThread2 implements Runnable{    @Override    public void run() {        Singleton2 s2 = Singleton2.getInstance();        s2.show();    }    }

 

登记式模式

内部类只有在外部类被调用才加载,产生SINGLETON实例,又不用加锁,此模式有上述俩模式的优点,屏蔽了他们的缺点,是最好的单例模式。
public class Singleton{    private Singleton(){}    public static Singleton getInstance(){ return Holder.SINGLETON;}    private static class Holder{//内部类        private static final Singleton SINGLETON= new Singleton();    }}

 

单例类的特点:
1、单例类确保自己只有一个实例
2、单例类必须自己创建自己的实例
3、单例类必须为其他对象提供唯一的实例。

单例类的优点:

(1) 控制资源的使用,通过线程同步来控制资源的并发访问。
(2)控制实例的产生数量,达到节约资源的目的。
(3)作为通信的媒介,数据共享。他可以在不建立直接关联的条件下,让多个不相关的两个线程或者多个进程之间实现通信。

 

单例类实用举例:Windows的任务管理器,打不开两个。 网站的计数器,不然很难实现同步。   数据库连接池的设计

 

单例模式的各种写法和总结 懒汉式 饿汉式 登记式