注意:这里只是看书,做下笔记,只为让自己思路更清晰,外加上自己的一点见解或者测试

饿汉式

public class Singleton {
    /**
     * 先私有构造函数,避免直接构造
     */
    private Singleton(){}
    /***
     * 饿汉式
     */
    private static final Singleton singleton = new Singleton(); 
    
    public Singleton getInstance(){
        return singleton;
    }
}

上面是饿汉式,由获取前对象已经创建,对象不会再轻易变化。只要对象不变化,那么多线程就不会出现问题,也就是说不会出现线程安全问题。

总结:

1.未获取已经创建,会浪费内存

2.使用简单,不存在线程安全问题

 

懒汉式

public class Singleton {
    /**
     * 先私有构造函数,避免直接构造
     */
    private Singleton(){}
    /***
     * 懒汉式,有需要才创建对象
     */
    private static volatile Singleton singleton = null; 
    
    public static synchronized Singleton getInstance(){
        if(singleton== null){
                System.out.println("进行");
                singleton = new Singleton();
        }
        return singleton;
    }

    public String toString() {
        return "Singleton=" + super.toString();
    }
}

线程获取单例对象,用于测试并发

public class ThreadGetSingleton  implements Runnable{

    public void run() {
        System.out.println(Thread.currentThread().getId()  + " --- Singleton=="+Singleton.getInstance());
    }

}

public class TestGetSington {
    public static void main(String[] args) {
        ThreadGetSingleton threadGetSingleton = new ThreadGetSingleton();
        ThreadGetSingleton threadGetSingleton2 = new ThreadGetSingleton();
        ThreadGetSingleton threadGetSingleton3 = new ThreadGetSingleton();
        ThreadGetSingleton threadGetSingleton4 = new ThreadGetSingleton();
        ThreadGetSingleton threadGetSingleton5 = new ThreadGetSingleton();
        ThreadGetSingleton threadGetSingleton6 = new ThreadGetSingleton();
        Thread thread1 = new Thread(threadGetSingleton);
        Thread thread2 = new Thread(threadGetSingleton2);
        Thread thread3 = new Thread(threadGetSingleton3);
        Thread thread4 = new Thread(threadGetSingleton4);
        Thread thread5 = new Thread(threadGetSingleton5);
        Thread thread6 = new Thread(threadGetSingleton6);
        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        thread5.start();
        thread6.start();
    }
}

 

运行结果:

懒汉式构建对象

懒汉式构建对象

懒汉式构建对象

15 --- Singleton==Singleton=sington2.Singleton@36fd35c5

懒汉式构建对象

懒汉式构建对象

14 --- Singleton==Singleton=sington2.Singleton@33918ac4

懒汉式构建对象

13 --- Singleton==Singleton=sington2.Singleton@26484d1e

12 --- Singleton==Singleton=sington2.Singleton@3661fa09

10 --- Singleton==Singleton=sington2.Singleton@5c2a3f44

11 --- Singleton==Singleton=sington2.Singleton@4968bb15

发现线程同时进去创建对象了,也就是说产生了线程并发的问题了。

 

上面是懒汉式,开始不会创建对象,防止内存消耗。按照需要创建,但是这样对象会变化。由于对象会产声变化,那么就会存在多线程并发问题,也就是我们常说的线程安全问题。

下面是加上同步锁的代码:

public class Singleton {

/**

 * 先私有构造函数,避免直接构造

 */

private Singleton(){}

/***

 * 懒汉式,有需要才创建对象

 */

private static volatile Singleton singleton = null; 

    public static synchronized Singleton getInstance(){

    if(singleton== null){

        System.out.println("懒汉式构建对象");

        singleton = new Singleton();

    }

    return singleton;

    }

    public String toString() {

        return "Singleton=" + super.toString();

    }

}