在此立贴为证,国庆一定要用MVP+OkHttp实现一个简单的登录,注册界面;一定一定,在此立贴为证!!!!!!
看了一些博客:现在总结一下自己的学习笔记,纯属记录:
单例模式的作用在于保证整个程序在一次运行的过程中,被单例模式声明的类的对象要有且只有一个
感觉总体是三步走:
第一步:先定义一个静态的对象,singleTon;
第二步:实现getInstance();
第三步:将构造方法私有化;
第一个是恶汉模式:不需要进行判空的操作,以为已经初始化了
public class EmptySingleTon
{
//先new一个对象,并初始化;
private static EmptySingleTon singleTon=new EmptySingleTon();
//
private static EmptySingleTon getInstance()
{
return singleTom;
}
//将构造方法私有化
private EmptySingleTon
{
}
}
第二个模式是懒汉模式:new对象的时候并未赋值,所以在getInstance 时需要进行判空的操作
public class LazySingleTon
{
private static LazySingleTon singleTon=null;
private static LazySingleTon getInstance()
{
if(single==null)
{
singleTon=new LazySigleTon();
}
return singleTon;
}
}
以上的在多线程的时候并不适用,因为在多线程的情况下可能会创建多个实例。
因而出现了第三种模式,在第二种的模式的基础上,上枷锁,锁住当前线程。用到关键字是synchronized。
public class SyncSingleTon {
private static SyncSingleTon singleTon=null;
//使用关键字对实现对线程的加锁,保证在执行getInsatnce时不会发生线程的切换
private static synchronized SyncSingleTong getInstance()
{
if(singleTon==null)
{
singleTon=new SyncSing();
}
return singleTon;
}
//另一种写法
// private static SyncSingleTon getInstance()
// {
// synchronized (SyncSing.class) {
// if(singleTon==null)
// {
// singleTon=new SyncSing();
//
// }
// }
// return singleTon;
// }
private SyncSingleTon()
{
}
}
但是还是存在不足,因为这种不管三七二十一就加锁,会大大降低效率,很费时,那么就要引入一个判断机制;判断的条件是什么:是否时第一次调用getInstance()方法,也就是判空,因为第一次都是空的啊!!
为什么这样写呢?我们来解释几个关键点:
1.为了防止new Singleton被执行多次,因此在new操作之前加上Synchronized 同步锁,锁住整个类(注意,这里不能使用对象锁)。
2进入Synchronized 临界区以后,还要再做一次判空。因为当两个线程同时访问的时候,线程A构建完对象,线程B也已经通过了最初的判空验证,不做第二次判空的话,线程B还是会再次构建instance对象。
看到这,是不是有一种豁然开朗的感觉。
https://blog.csdn.net/bjweimengshu/article/details/78716839?utm_source=copy
public class SyncSingleTon {
private static SyncSingleTon singleTon=null;
//静态工厂方法
private static SyncSingleTon getInstance()
{
if(singleTon==null)//双重检测机制
{
synchronized(SyncSingleTon.class);//同步锁
if(singleTon==null)//双重检测机制
{single=new SyncSingleTon();
}
}
return singleTon;
}
//私有化构造函数
private SyncSingleTon{}
}
但是还是有问题的,因为存在一种指令重排的情形,就是jvm不一定会按照我们的指令顺序执行,为什么,这里就不多作介绍,因为为哦还是懵逼的,涉及到java虚拟机的底层操作,解决方法是加个关键字volatile,可以阻止程序的指令重排.
public class Volatile {
//Volatile,保证了指令重排序在这个对象创建的时候不可用.
//什么是指令重排序,就是(java虚拟机)在执行我们的代码时,并不是按照我们的顺序来的,会根据一些规则进行重新排序
private volatile static Volatile singlieTon=null;
private static Volatile getInstance(){
if(singlieTon==null)
{
synchronized (Volatile.class) {
if(singlieTon==null)
singlieTon=new Volatile();
}
}
return singlieTon;
}
private Volatile()
{
}
}
还有一种单例模式,使用静态类.
这个稍微有点拗口,what is 静态类?
我们可以有如下思路:
- 返回该类的对象依赖于一个静态内部类的初始化操作。
- 在这个静态内部类初始化的时候,生成外部类的对象,然后在
getInstance
中返回
public static StaticSingleTon
{
private static class innersingleclass
{
private StaticSingleTon singleTon=new StaticSngleTon();
}
private static StaticSingle getInstance()
{
return innnersingleclass.singleTon;
}
private StaticSingle
{
}
}
最后会有一个终极模式:
利用Enum来实现单例模式
最后盗个图来总结一下以上的单例模式: