单例设计模式是一种最常见的设计模式,其目的就是为了保证整个程序中只有一个实例,常见的场景都是一些特殊的类,比如管理类的实现。
实现单例模式方法:
1.构造函数私有,防止在外部 new 对象。
2.内部提供一个静态的方法,让外部调用来获取这个单例。
饿汉式单例
/**
* Created by zhangl on 2019/1/2.
*
*
* 单例 - 饿汉式 随着类的加载,就已经new了对象
*
*/
public class Singleton1 {
private static Singleton1 mInstance = new Singleton1();
private Singleton1(){
}
public static Singleton1 getInstance(){
return mInstance;
}
}
懒汉式单例
/**
* Created by zhangl on 2019/1/2.
*
* 单例 - 懒汉式 只有在使用的时候才会去加载
*
*/
public class Singleton2 {
private static volatile Singleton2 mInstance;
private Singleton2(){
}
public static Singleton2 getInstance(){
if (mInstance == null){
synchronized (Singleton2.class){
if (mInstance == null){
mInstance = new Singleton2();
}
}
}
return mInstance;
}
}
代码中可以看到使用了volatile关键字,加上volatile关键的目的:
1.防止从排序 - JMM通过happens-before法则保证顺序执行语义,如果想要让执行操作B的线程观察到执行操作A的线程的结果,那么A和B就必须满足happens-before原则,否则,JVM可以对它们进行任意排序以提高程序性能。
2.线程可见性 - 多线程环境下,某个共享变量如果被其中一个线程给修改了,其他线程能够立即知道这个共享变量已经被修改了,当其他线程要读取这个变量的时候,最终会去内存中读取,而不是从自己的工作空间中读取。
关于volatile关键字,可以写一个测试类:
/**
* Created by zhangl on 2019/1/2.
*/
public class VolatileTest {
public static void main(String[] args) {
ThreadDemo td = new ThreadDemo();
new Thread(td).start();
while(true){
if(td.isFlag()){
System.out.println("------------------");
break;
}
}
// 执行结果? flag= true ------------------
}
}
class ThreadDemo implements Runnable {
private volatile boolean flag = false;
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
}
flag = true;
System.out.println("flag=" + isFlag());
}
public boolean isFlag() {
return flag;
}
public void setFlag(boolean flag) {
this.flag = flag;
}
}
测试结果如下:
volatile测试.png
利用单例模式实现Activity管理类:
/**
* Created by zhangl on 2019/1/2.
*
*
* Activity 管理类
*
*
*/
public class ActivityManager {
private static volatile ActivityManager mInstance;
private Stack<Activity> mActivitys;
private ActivityManager(){
mActivitys = new Stack<>();
}
public void attach(Activity activity){
mActivitys.add(activity);
}
public void detach(Activity detachActivity){
// 一边循环一边移除 会出问题
/*for (Activity activity : mActivities) {
if(activity == detachActivity){
mActivities.remove(activity);
}
}*/
int size = mActivitys.size();
for (int i = 0;i < size;i++){
Activity activity = mActivitys.get(i);
if (activity == detachActivity){
mActivitys.remove(i);
i--;
size--;
}
}
}
/**
* 获取当前Activity
* @return
*/
public Activity getCurrentActivity(){
return mActivitys.lastElement();
}
}
网友评论