JAVA学习笔记(三)
前言:
这周忙的不行,没学多少东西,就简单的学习下Java的单例吧。
设计模式之单例
单例模式是最简单也是最常用的设计模式,在学习OC的过程中第一个接触的设计模式就是单例,所以从单例入手来了解Java的一些特性也是极好的。
1.懒汉式单例
public class JMSingleManager {
private JMSingleManager() {}
private static JMSingleManager instance = null;
//类方法
public static JMSingleManager shareInstance() {
if (instance == null) {
instance = new JMSingleManager();
}
return instance;
}
}
1.为了实现在整个软件的生命周期内这个类只能存在唯一一个实例,我们必须把Java默认提供的构造器私有化,这样在外部就不能new一个对象了。
2.置于为什么要用类方法去实现单例,是因为类必须实例化一个类之后才能调用实例方法,总不能为了得到单例每次都要重新new一个对象吧,这样写十分怪异,并且性能也很差。
3.由于类方法只能访问类中的静态成员变量,所以该对象的定义也必须声明为static。
我们发现Java的单例写法和OC中的写法基本一致,但是很容易发现的一个问题就是这种创建方式是线程不安全的,多个线程同时访问可能会实例化多次,所以我们必须加上线程锁,就像在OC中使用dispatch_once一样,但是最常用的还是synchronized这个方法,在Java中也有synchronized,在使用上也和OC非常相像,我们把代码改成下面这样:
public static JMSingleManager shareInstance() {
if (instance == null) {
synchronized(JMSingleManager.class){
instance = new JMSingleManager();
}
}
return instance;
}
在这里我们用synchronized
修饰JMSingleManager
这个类,类的所有对象共用一个锁,synchronized
不仅可以用来修饰类,还能修饰指定的对象,也可以修饰实例方法、类方法,而且也可以修饰一个代码块,比如上述的代码可以改成下面这样:
public static synchronized JMSingleManager shareInstance() {
if (instance == null) {
instance = new JMSingleManager();
}
return instance;
}
这里还有一种写法,需要借助Java的关键字final
:
final:被final修饰的类无法被继承,被final修饰的方法无法被重写,被final修饰的变量只能被初始化一次,这里我们就要用这个特性,而且被final修饰的变量是天然线程安全的(因为只能初始化一次啊!)
所以单例我们可以这样写:
public class JMSingleManager {
private static class LazyHolder {
private static final JMSingleManager instance = new JMSingleManager();
}
private JMSingleManager (){}
public static final JMSingleManager shareInstance() {
return LazyHolder.instance;
}
}
2.饿汉式单例
public class JMSingleManager {
private JMSingleManager (){}
private static JMSingleManager instance = new JMSingleManager();
public static JMSingleManager shareInstance() {
return instance;
}
}
这里主要通过Java的类加载机制来规避线程不安全的风险,也是最简单与最方便的写法。
关于Java的类加载机制个人现在了解的还十分浅薄,以后等了解深一点再来聊聊。