目录
单例模式的含义
饿汉模式
注意事项
懒汉模式
单线程版本
多线程版本
多线程改进版本(推荐)
注意事项
单例模式的含义
解析这个名词:
单例中的单,指的是单个,一个的意思
而例,是实例的意思,实例也就是通常所说的对象.
合起来就是,只能有一个实例\对象的模式.
当然这是对于某一个类来说的.
在使用了这个模式后,我们就不能一直new一直new来创建多个对象了.会被这个模式下的java语法所限制,从而达到某个类只能含有一个类的情况.
单例模式的具体实现方法,对应的也分成饿汉模式与懒汉模式和其他方法,这里着重介绍这两种.
饿汉模式
在创建类的时候顺手就把实例创建好(特点),并且把构造方法使用private修饰使用户在类外无法创建实例.达到有且只有一个实例的效果.
public static class Singleton{
private static Singleton instance = new Singleton();//private修饰的且static
private Singleton(){};
public static Singleton getInstance(){//返回的类型为自定义类型
return instance;
}
}
注意事项
①类中创建的实例需要使用类名修饰,是一个自定义类型.
②使用InputContext类下的类方法getInstance方法返回类中唯一的实例,使其可以在类外使用
③唯一的实例是需要被static修饰,原因是:
当在类外调用类方法的时候,可以通过创建一个新的实例通过这个新的实例调用其中的类方法.或者直接调用这个类的类方法(即静态方法).这一来就规定了,getInstance方法只有通过被static修饰在类外直接调用的这种方法.
而静态的方法,即类方法.是不可以访问非静态的实例或者变量的.这时候就需要我们把实例再加上static关键字,使其能够被返回
④还要注意的是,为了达到唯一这个关键点.我们需要将其构造方法挂上private关键字来修饰,使其不能被在类外调用.
⑤饿汉模式的特点为,在创建类的时候就已经把实例创建好了.不管后面的程序有没有使用到这个实例.
⑥在多线程的模式下,是线程安全的.因为饿汉模式中只有读指令
懒汉模式
在getInstance方法中判断实例有无创建,如果第一个实例还没有创建则创建第一个实例.
能够放置后续代码没有使用这个实例,而却先前创建出来.浪费了空间资源
单线程版本
public static class Singleton1{
private static Singleton1 instance = null;
private Singleton1(){};
public static Singleton1 getInstance(){
if(instance == null){//在调用的时候才创建实例
instance = new Singleton1();
}
return instance;
}
}
多线程版本
只是在单线程的基础上,加上synchronized关键字,对getinstance方法上锁
对getInstance方法上锁,防止多线程的环境下可能创建出多个实例的情况.
public static class Singleton2{
private static Singleton2 instance = null;
private Singleton2(){};
public static synchronized Singleton2 getInstance(){//上锁
if(instance == null){
instance = new Singleton2();
}
return instance;
}
}
多线程改进版本(推荐)
在上面的基础上,将锁放到了内部.
对于单例模式的多线程下,会出现线程安全问题的只有实例需要被创建但还没创建出的情况.
将锁放到getinstance方法外面,再每次调用getinstance方法的时候都会进行上锁和销毁锁的操作.
可是锁的创建与销毁也是需要一定的开销的.
为了尽量避免这种开销,我们可以将锁放到里面.使用两个if语句来判断.外面的if通常适用于,实例已经创建后的状况下会使用次数比较多.而对于第二个if语句,只会在第一次创建实例的时候进入,
但在内部上锁,就会出现线程的内存可见性的问题,所以需要volatile关键字来修饰实例.
public static class Singleton3{
private static volatile Singleton3 instance = null;
private Singleton3(){};
public static Singleton3 getInstance(){
if(instance == null){
synchronized (Singleton3.class){
if(instance == null){
instance = new Singleton3();
}
}
}
return instance;
}
}
注意事项
①只有在类外调用getInstance方法的时候才创建实例,在一定程度上避免了资源的浪费
②在多线程环境下,饿汉模式并非天然就是线程安全的.因为其包含了读操作也包含有写操作.文章来源:https://www.toymoban.com/news/detail-606261.html
③在多线程的环境下,使用饿汉模式最好使用改进后的版本.在合适的位置使用synchronized关键字上锁,并且使用volatile修饰实例.减少了上锁与销毁锁的次数,节约了资源,也有更高效的效率.文章来源地址https://www.toymoban.com/news/detail-606261.html
到了这里,关于[JAVAee]单例模式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!