• 引言
  • 单例设计模式的实现
  • 1 单例之饿汉模式
  • 2 单例之饿汉模式 静态代码块
  • 3 单例之懒汉模式 多线程有问题
  • 4 单例之懒汉模式 多线程解决方案一
  • 5 单例之懒汉模式 多线程解决方案二
  • 总结


1.引言

      在本篇博客中主要介绍单例设计模式在多线程中的应用。什么是单例设计模式?单例设计模式就是只在内存中创建一份对象单例设计模式就是只在内存中创建一份对象单例设计模式就是只在内存中创建一份对象。这有什么作用呢?举个例子,在窗体程序中:点击一个按钮,弹出一个窗体。一般来说,如果子窗体已经创建了,那么就不需要创建新窗体了。这个时候就用到了单例设计模式。如果不使用单例设计模式,那么点10下按钮,就会弹出10个窗体,这显然是不符合现实要求的。

2.单例设计模式的实现

      关于单例设计模式的实现有几种方式。比如:饿汉模式懒汉模式,其中饿汉模式在多线程中需要进行特殊的处理。

      单例设计模式的大妈实现大致分为两步:

  • 将单例类的构造函数设为private
  • 提供public方法用于获得类的实例

2.1 单例之饿汉模式

饿汉模式在使用类的时候已经将对象创建完毕

  • 创建类(Singleton
public class Singleton {
    private static Singleton instance=new Singleton();
    private Singleton(){

    }
    public static Singleton  getInstance()
    {
        return instance;
    }
}

注意两点:
1.将构造函数私有化了
2.提供了共有方法可以得到Singleton实例变量

2.2 单例之饿汉模式 (静态代码块)

      在上述例子中存在一定的缺点:如果我想在创建对象之间做一定的逻辑处理,应该怎么办呢?我们可以通过静态代码块来实现饿汉模式的单例。

  • 创建类(Singleton
public class Singleton {
    private static Singleton instance;
    static {
        //这里可以写一定的逻辑运算
        instance=new Singleton();
    }
    private Singleton(){

    }
    public static Singleton  getInstance()
    {
        return instance;
    }
}

2.3 单例之懒汉模式 (多线程有问题)

      懒汉模式也叫做延迟加载,延迟加载就是说,当我们调用getInstance()方法的时候才会创建实例。
      首先我们看一下在单线程中,单例设计模式(懒汉模式)是如何实现的。

  • 创建类(Singleton
public class Singleton {
    private static Singleton instance;
    private Singleton(){

    }
    public static Singleton  getInstance() throws Exception
    {
        if(instance==null)
        {   
            //模式创建实例之前需要做一定的处理
            Thread.sleep(2000);
            instance=new Singleton();
        }
        return instance;
    }
}
  • main函数中的实现
//创建了四个实例
public class App {
    public static void main(String[] args) throws Exception {
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());
        System.out.println(Singleton.getInstance());

    }

}
  • 运行结果(单线程没有问题)

JAVA单机程怎么运用多机程 java多线程单例模式_多线程

  • 现在我们创建一个线程类
public class MyThread extends Thread {
        @Override
        public void run() {
            try {
                System.out.println(Singleton.getInstance());
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
}
  • 此时我们创建三个线程
public class App {
    public static void main(String[] args) throws Exception {
        MyThread a=new MyThread();
        MyThread b=new MyThread();
        MyThread c=new MyThread();
        a.start();
        b.start();
        c.start();

    }
}
  • 运行结果(出现问题,并不是一个实例)

JAVA单机程怎么运用多机程 java多线程单例模式_设计模式_02

2.4 单例之懒汉模式 (多线程解决方案一)

  • 相比于2.,我们只修改Singleton类(添加了synchronized关键字)
public class Singleton {
    private static Singleton instance;
    private Singleton(){

    }
    public synchronized static  Singleton  getInstance() throws Exception
    {
        if(instance==null)
        {   
            //模式创建实例之前需要做一定的处理
            Thread.sleep(2000);
            instance=new Singleton();
        }
        return instance;
    }
}
  • 运行结果(没问题)

JAVA单机程怎么运用多机程 java多线程单例模式_JAVA单机程怎么运用多机程_03

2.5 单例之懒汉模式 (多线程解决方案二)

上面的代码还是有一定的缺点,缺点是:影响了代码的效率。代码的重点在创建单例的时候,所以想要提高效率不应该把整个方法同步,可以尝试将创建实例的语句同步(同步代码块),接下来我们再看修改之后的getInstance()方法。

public class Singleton {
    private static Singleton instance;

    private Singleton() {

    }

    public static Singleton getInstance() throws Exception {
        if (instance == null) {
            // 模式创建实例之前需要做一定的处理
            Thread.sleep(2000);
            synchronized (Singleton.class) {
                if (instance == null) {
                    //注意这里是双重判断
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
  • 运行代码(速度提高了,并且也是单例)

JAVA单机程怎么运用多机程 java多线程单例模式_多线程_04

3.总结

      在此篇博客中主要记录了:

  • 单例设计模式在多线程中的应用
  • 如何设计线程安全的单例设计模式
  • 在本博客中提供了几种单例设计模式的实现