前页:设计模式总述
单例模式是java中最简单的一种设计模式。所谓单例模式,就是整个程序只允许有一个类的实例,并且向整个系统中提供此事例。有点像C++中被定义为static的变量。
比如当我们某个程序只有一个关于打印机的端口,那么我们必须将这个端口设计为单例的,因为如果当多台电脑使用这个打印机的时候,只允许第一台电脑对此进行操作,否则打印机将引起混乱,
说了不少,但是还是不清楚什么是单例模式。作为程序猿,我们更直观的是通过代码了解一个模式。
在说代码之前,我们要说说单例模式的前提内容:
上一种通俗意义上的单例模式代码:
public class SingleClass {
//创建对象
private static SingleClass singleClass = new SingleClass();
//设置为私有成员函数,无法在类外被实例化
private SingleClass(){}
//设置唯一获取singleClass对象的方法
public static SingleClass getSingleClass(){
return singleClass;
}
//设置方法表明实例化该对象
public void show(){
System.out.println("方法已被实例化");
}
}
public class SingleMode {
public static void main(String[] args) {
//会报错,由于这种实例化被设置为私有函数,不被允许类外访问
//SingleClass singleClass = new SingleClass();
SingleClass singleClass = SingleClass.getSingleClass();
//调用函数
singleClass.show();
}
}
public class SingleClass {
private static SingleClass singleClass;
private SingleClass() {}
public static SingleClass getSingleClass() {
if (singleClass == null) {
singleClass = new SingleClass();
}
return singleClass;
}
}
由于上述代码没有对SingleClass加锁,因此线程不安全。
public class SingleClass {
private static SingleClass singleClass;
private SingleClass() {}
public static synchronized SingleClass getSingleClass() {
if (singleClass == null) {
singleClass = new SingleClass();
}
return singleClass;
}
}
对方法getSingleClass加锁,保证每次只能有一个线程访问该方法,可以用于多线程。但是也由于上锁之后,该方法效率降低。适用于不频繁调用个SingleClass的程序。
public class SingleClass {
private static SingleClass singleClass = new SingleClass();
private SingleClass() {}
public static SingleClass getSingleClass() {
return singleClass;
}
}
该方法由于没有加锁,所以执行效率会比较高,但是类在加载的时候会初始化,造成内存浪费。
那么这个方法是线程安全的么?当然是。
这涉及到JVM的一些内容,在JVM中,类加载初始化时就创建好一个静态的对象供外部使用。因此本身就是线程安全的。(唉,不会的东西太多了,课程还复杂,有时间再看看《深入理解JAVA虚拟机》吧)
public class SingleClass {
private static volatile SingleClass singleClass;
private SingleClass() {}
public static SingleClass getSingleClass() {
if (singleClass == null) {
synchronized (SingleClass.class) {
if (singleClass == null) {
singleClass = new SingleClass();
}
}
}
return singleClass;
}
}
volatile关键字和synchronized关键字区别就是:volatile不具备原子性。因此多线程访问volatile修饰时,若未执行完将会回滚。
该实现方式利用了双重锁,当singleClass为空的时候,锁住该类,进行对象的初始化。线程安全,且在进入实例化方法的时候再对该类上锁,提升了程序的运行效率。
public class SingleClass {
private static class SingletonHolder {
private static final SingleClass singleClass = new SingleClass();
}
private SingleClass() {}
public static final SingleClass getSingleClass() {
return SingletonHolder.singleClass;
}
}
这种方式,利用public static final 关键字,在显式调用getSingleClass方法的时候,将类和变量初始化并装载在常量区(即不可被改变)。因此这条特性决定了多线程的安全。
public enum SingleClass{
singleClass;
public void method(){
System.out.println(singleClass+"枚举最简单!");
}
}
public class SingleMode {
public static void main(String[] args) {
SingleClass singleClass =SingleClass.values()[0];
singleClass.method();
}
}
虎躯一震······这也太简单了吧。。他自动支持序列化机制,绝对防止多次实例化。
singleClass是一个常量,enum本身也是线程安全的,因此也不存在被改写的情况。。。。
有一些地方待更新!