什么是单列模式?
百度百科:单例模式,属于创建类型的一种常用的软件设计模式。通过单例模式的方法创建的类在当前进程中只有一个实例(根据需要,也有可能一个线程中属于单例,如:仅线程上下文内使用同一个实例)。
1.懒汉式
/**
* created by panshimu
* on 2019/10/24
* 懒汉式-单列模式
*/
public class Single01 {
public static Single01 mSingle01;
private Single01(){
}
/**
* 存在多线程并发问题 可能会存在多个实列
* @return
*/
public static Single01 getInstance(){
if(mSingle01 == null){
mSingle01 = new Single01();
}
return mSingle01;
}
}
2.饿汉式
/**
* created by panshimu
* on 2019/10/24
* 饿汉式-单列模式
*/
public class Single02 {
//随着类的加载就创建对象
public static Single02 mSingle02 = new Single02();
private Single02(){
}
public static Single02 getInstance(){
return mSingle02;
}
}
3.线程安全
/**
* created by panshimu
* on 2019/10/24
*/
public class Single05 {
public static Single05 mSingle05;
private Single05(){
}
/**
* 加同步锁 能解决同步问题 但是会影响效率 因为每一次都要加锁的判断
* @return
*/
public static synchronized Single05 getInstance(){
if(mSingle05 == null){
mSingle05 = new Single05();
}
return mSingle05;
}
}
4.线程和效率
/**
* created by panshimu
* on 2019/10/24
*/
public class Single06 {
//防止重排序 线程可见
public static volatile Single06 mSingle06;
private Single06(){
}
/**
* 既保证线程安全 效率也还是比较高的
* @return
*/
public static Single06 getInstance(){
if(mSingle06 == null){
synchronized (Single06.class){
if(mSingle06 == null){
mSingle06 = new Single06();
}
}
}
return mSingle06;
}
}
第四种 单列模式中 既保证了线程的安全 又提高了效率,但是还是存在问题的。
比如 线程的不可性,重排序问题。在多线程的情况下。
线程的可见行:某一个线程中改变了某一个公共对象或是公共变量,短时间内可能会存在在某一个线程是不可见的,意思就是在某一个线程中这个值可以还是原来的值。因为每一个线程都有自己的缓存区。
看下面的列子:
public static void main(String[] args){
VolatileThread volatileThread = new VolatileThread();
new Thread(volatileThread).start();
while (true){
if(volatileThread.isFlag()){
System.out.println("00000000000000000000");
break;
}
}
}
static class VolatileThread implements Runnable{
private boolean flag = false;
@Override
public void run() {
try{
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
flag = true;
System.out.println("flag="+flag);
}
public boolean isFlag(){
return flag;
}
}
执行上面的列子,发现 System.out.println("00000000000000000000"); 并没有执行,实际上 flag=true 了。但是 volatileThread.isFlag() 返回的还是 false 所以说短时间内 值还没有被改变。
怎么解决这个问题呢?
只需要给 flag 变量加上 volatile 关键字 就可以了。
在4中把改为
public static volatile Single05 mSingle05;
就可以了。
5.静态内部类
保证线程的安全 用到的时候才会new
/**
* created by panshimu
* on 2019/10/24
* 静态内部类
*/
public class Single04 {
private Single04(){
}
public static Single04 getInstance(){
return Single04Holder.mSingle04;
}
public static class Single04Holder{
private static volatile Single04 mSingle04 = new Single04();
}
}
6.容器管理
/**
* created by panshimu
* on 2019/10/24
* 容器管理
*/
public class Single07 {
private static Map<String,Object> mSingleMap = new HashMap<>();
private Single07(){
}
static {
mSingleMap.put("miaozi",new Single07());
}
public static Object getInstance(String str){
return mSingleMap.get(str);
}
}
好了 ,单列模式就到这里啦。
网友评论