Android构建
1.Android构建流程
把java变成我们熟悉的.class字节码文件,在把字节码文件和我们所依赖的第三方的jar文件打包程class.dex安卓可执行的文件,再打包我们的资源文件,最后在把我们的index文件和cef文件编程我们未签名的包,通过签名打成一个完整的包,这样是我们完整的构建流程。
单例设计模式
恶汉
private class HungrySingleton{
private static final HungrySingleton instance=new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return instance;
}
}
不足之处:无法instance实例做延时加载
优化:懒汉模式
懒汉
private class LazySingleton{
private static LazySingleton instance=null;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if(instance==null){
instance=new LazySingleton();
}
return instance;
}
}
不足之处:在多线程并发下这样的实现无法保证实例是唯一的
优化:懒汉线程安全
懒汉线程安全
private class LazySafeSingleton{
private static LazySafeSingleton instance=null;
private LazySafeSingleton(){
}
//方法中使用synchronized关键字
public static synchronized LazySafeSingleton getInstance(){
if(instance==null){
instance=new LazySafeSingleton();
}
return instance;
}
//同步代码块实现
public static LazySafeSingleton getInstance1(){
synchronized (LazySafeSingleton.class){
if(instance==null){//懒汉式
instance=new LazySafeSingleton();
}
}
return instance;
}
}
不足之处:性能
优化:DCL
DCL<双重锁机制>
private class DclSingleton {
private static volatile DclSingleton instance=null;
private DclSingleton() {
}
public static DclSingleton getInstance1() {
//避免不必要的同步
if (instance == null) {
//同步
synchronized (DclSingleton.class) {
//在第一次初始化时调用
if (instance == null) {//懒汉式
instance = new LazySafeSingleton();//这个代码不是原子操作,在jvm当中的逻辑,第一步会做这样一个事,
//首先按照我们的逻辑,第一步会给instance分配内存,第二步会调用我们DclSingleton的构造方法来初始的变量,
//第三步就会将我们的instance的这个对象指向我们的jvm分配的内存空间
//但是jvm有这样一个缺点,他在即时编译器中存在指令重排序的优化。也就是说以上说的三步他不会按照我们想要的顺序执行,
//有可能第三步会在第二步之前,也有可能第二步会在第一步之前执行,所以说这样就会造成我们的线程不安全,也会造成我们的报错
//。解决办法只要将我们的instance变量设置成volatile就可以了。
//volatile的原因是可见性,他能保证线程在本地不会存有instance副本,而每次都会去我们的内存中去读取。
//但事实上这种观念是不全面的,因为我们使用volatile这个关键字的主要原因是他可以禁止我们jvm的指令重排序。这样第三步就不会跳到第二步去了。
// 另外volatile这个操作会有一个内存屏障,读操作的时候不会排序到内存屏障之前,比如说我们刚才所说的1,2,3的顺序,他不会在1,3,2之后,
//不存在这个重排序的情况。
}
}
}
return instance;
}
}
不足之处:JVM的即时编译器中存在指令重排序的优化
优化:静态内部类/枚举
静态内部类
public class StaticInnerSingleton {
private StaticInnerSingleton() {
}
public static StaticInnerSingleton getInstance() {
return SingletonHolder.instance;
}
//静态内部类
private static class SingletonHolder{
private static final StaticInnerSingleton instance=new StaticInnerSingleton();
}
}
不足之处:JVM本身机制保证了线程安全/没有性能缺陷
原因:static/final
好处
(1)jvm本身的机制保证了我们的线程安全
(2)我们并没有使用关键字synchronized,synchronized虽然能保证线程安全,但是他其实非常影响性能,因为 他 只有一个线程去读取里面的数据,这样读书线程的时候另外的线程就不能读取了,而静态内部类就不一样了,他可以同时读取实例,这样就提高我们的效率
(3) 就是我们的SingletonHolder这个类是私有的,除了我们的getInstance()的方法,其他的方法没有办法访问他
枚举 -----java5之后才出现
public enum EnumSingleton {
//定义一个枚举的元素,它就是Singleton的一个案例
INSTANCE;
public void doSomeThing(){
//do someString.....
}
}
优点:写法简单/线程安全不写另外的实例方法,这个枚举是线程安全的。但是如果要添加其他的实例变量和实例方法一定要注意线程安全
总结
饿汉:无法对instance实例进行延迟加载
懒汉:多线程并发情况下无法保证实例的唯一性
懒汉线程安全:使用synchronized导致性能缺陷
DCL:JVM即使编译器的指令重排序
静态内部类/枚举:延迟加载/线程安全/性能优势