- 引言
- 单例设计模式的实现
- 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());
}
}
- 运行结果(单线程没有问题)
- 现在我们创建一个线程类
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();
}
}
- 运行结果(出现问题,并不是一个实例)
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;
}
}
- 运行结果(没问题)
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;
}
}
- 运行代码(速度提高了,并且也是单例)
3.总结
在此篇博客中主要记录了:
- 单例设计模式在多线程中的应用
- 如何设计线程安全的单例设计模式
- 在本博客中提供了几种单例设计模式的实现