单例模式

单例模式有三种:

  • 饿汉模式:提前初始化好对象,需要的时候直接调用

package com.whereta.singleton;

/**
 * Vincent 创建于 2016/4/15.
 * 该模式是提前初始化好对象,调用的时候直接返回即可
 */
public class SingletonClass1 {
    //一定要将默认的构造函数设为私有,不能实例化
    private SingletonClass1() {

    }

    private static SingletonClass1 instance = new SingletonClass1();

    public static SingletonClass1 getInstance() {
        return instance;
    }

    public void test(){
        System.out.println("我是:"+this);
    }




}

  • 懒汉模式-双重检查加锁:在调用的时候检查对象是否实例化,如果没有实例化则实例化返回

package com.whereta.singleton;

/**
 * Vincent 创建于 2016/4/15.
 * 该模式是懒汉模式,在具体使用的时候初始化。采用双重检查加锁方式保证线程安全,
 */
public class SingletonClass2 {
    //一定要将默认的构造函数设为私有,不能实例化
    private SingletonClass2() {

    }

    private static SingletonClass2 instance = null;

    public static SingletonClass2 getInstance() {

        if (instance == null) {
            //如果为空,加锁开始初始化
            synchronized (SingletonClass2.class) {
                SingletonClass2 temp = instance;
                if (temp == null) {
                    //此处保存对象创建成功之后再返回,如果不添加temp,则会出现问题:
                    // 当instance先分配内存空间,未完成数据设置,此时instance不为null,如果有新的线程进入请求,直接返回instance,由于没有数据报错
                    synchronized (SingletonClass2.class) {
                        temp = new SingletonClass2();
                    }
                    instance = temp;
                }
            }
        }
        return instance;
    }

    public void test() {
        System.out.println("我是:" + this);
    }


}

  • 懒汉模式-内部类


  • package com.whereta.singleton;
    
    /**
     * Vincent 创建于 2016/4/15.
     * 该模式是懒汉模式,通过内部类实现线程安全,只有在调用内部类的时候才会加载实例
     */
    public class SingletonClass3 {
        //一定要将默认的构造函数设为私有,不能实例化
        private SingletonClass3() {
    
        }
    
        private static class StaticSingletonClass3 {
            private static SingletonClass3 intance = new SingletonClass3();
        }
    
        private static SingletonClass3 instance = null;
    
        public static SingletonClass3 getInstance() {
            return StaticSingletonClass3.intance;
        }
    
        public void test() {
            System.out.println("我是:" + this);
        }
    
    
    }

测试:

package com.whereta.singleton;

import org.freebencher.FbJobResult;
import org.freebencher.FbTarget;
import org.freebencher.Freebencher;

/**
 * Vincent 创建于 2016/4/15.
 */
public class Main {
    public static void main(String[] args) {

        FbJobResult result = Freebencher.benchmark(new FbTarget() { //the behavior
                                                       public boolean invoke() {
                                                           SingletonClass1 singletonClass1 = SingletonClass1.getInstance();
                                                           singletonClass1.test();

                                                           return true;
                                                       }
                                                   }, 20, // concurrency,
                10 // number of tests to run
        );

        System.out.println(result.report());

    }
}

结果:

Connected to the target VM, address: '127.0.0.1:62908', transport: 'socket'
Test started.
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
Awaiting termination...
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
我是:com.whereta.singleton.SingletonClass2@1aa0e220
100/100 are done
Test completed.
Concurrency:             50
Time taken for tests:    31ms
Successful tests:        100
Failed tests:            0
Tests per second:        3225.8064516129034
Mean time per test:      0.98ms
Percentage of the test finished within a certain time (ms)
50%:                     1
60%:                     1
70%:                     1
80%:                     2
90%:                     3
95%:                     3
98%:                     4
99%:                     4
100%:                    4

Disconnected from the target VM, address: '127.0.0.1:62908', transport: 'socket'

Process finished with exit code 0

通过输出:所有对象都是相同的,也就是只有一个实例。

以上三种方式都是线程安全的,可以放心在多线程环境下使用

  • 双重加锁方式代码比较繁琐,不推荐使用,并且在初始化的时候会加锁,一定程度影响效率

  • 饿汉模式是在程序启动的时候就初始化完成,无法是否使用就一直存在,看需求选择是否使用该方式

  • 内部类方式就保证了线程安全,也是一种懒加载模式,代码也比较简洁,推荐



个人博客:http://www.whereta.com

你可能感兴趣的:(单例模式)