比如一个团队多个开发者都需要操作日志文件,如果每个人都实例化一个日志对象,会导致不必要的开销。为了解决这类问题,单例模式产生了。单例模式保证一个类仅有一个实例,并提供一个访问它的全局访问点。Windows系统中的回收站就是典型的一种单例模式应用,多次打开回收站不会创建新的窗口。
package SingletonPattern;
public class Singleton01 {
    private static final Singleton01 INSTANCE = new Singleton01();
    private Singleton01(){};
    public static Singleton01 getInstance(){return INSTANCE;}
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        Singleton01 m1 = Singleton01.getInstance();
        Singleton01 m2 = Singleton01.getInstance();
        System.out.println(m1 == m2);
    }
}
package SingletonPattern;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class Singleton02 {
    //不能定义为final型,因为常量需要初始化
    private static Singleton02 INSTANCE;
    private Singleton02(){
    }
    public static Singleton02 getInstance(){
        if(INSTANCE == null){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Singleton02();
        }
        return INSTANCE;
    }
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
//同一类的不同对象hashcode是不同的
            new Thread(()->{
                System.out.println(Singleton02.getInstance().hashCode());
            }).start();
        }
    }
}
1184893857
219573733
449584288
1924898670
103512977
585605895
967740059
1802506717
499531361
1416599099
当多线程操作时,懒汉模式会出现,线程不安全的问题,比如A,B两个线程同时首次创建单例对象,A线程进入判空条件,创建对象之前,B线程此时INSTANCE依然为空,此时A,B线程会创建两个对象。
package SingletonPattern;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class Singleton03 {
    //不能定义为final型,因为常量需要初始化
    private static Singleton03 INSTANCE;
    private Singleton03(){
    }
    public static synchronized Singleton03 getInstance(){
        if(INSTANCE == null){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            INSTANCE = new Singleton03();
        }
        return INSTANCE;
    }
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
            new Thread(()->{
                System.out.println(Singleton03.getInstance().hashCode());
            }).start();
        }
    }
}
1416599099
1416599099
1416599099
1416599099
1416599099
1416599099
1416599099
1416599099
1416599099
1416599099
package SingletonPattern;
import org.omg.PortableServer.THREAD_POLICY_ID;
public class Singleton04 {
    //不能定义为final型,因为常量需要初始化
    private static volatile Singleton04 INSTANCE;
    private Singleton04(){
    }
    public static synchronized Singleton04 getInstance(){
        if(INSTANCE == null){
            synchronized (Singleton04.class) {
                if(INSTANCE == null) {
                    INSTANCE = new Singleton04();
                }
            }
        }
        return INSTANCE;
    }
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
            new Thread(()->{
                System.out.println(Singleton04.getInstance().hashCode());
            }).start();
        }
    }
}
package SingletonPattern;
import sun.applet.AppletResourceLoader;
/**
 * 静态内部类方式
 */
public class Singleton05 {
    private Singleton05(){};
    private static class Singleton05Holder{
        private final static Singleton05 INSTANCE = new Singleton05();
    }
    public static Singleton05 getInstance(){
        return Singleton05Holder.INSTANCE;
    }
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
            new Thread(()->{
                System.out.println(Singleton05.getInstance().hashCode());
            }).start();
        }
    }
}
package SingletonPattern;
public enum Singleton06 {
    INSTANCE;
    public void method(){
        System.out.println("Happy Everyday");
    }
    public static void main(String[] args) {
        for(int i = 0; i < 10; i++){
            new Thread(()->{
                System.out.println(Singleton05.getInstance().hashCode());
            }).start();
        }
    }
}
原文:https://www.cnblogs.com/happysml/p/13849959.html