单例模式主要分为两种懒汉和饿汉模式,其实就是所谓的是否有类的懒加载,以及线程安全方面的考虑、
单例核心就是单例模式八钟的其中七钟都是基于【1.私有的构造函数,2.静态的获取对象方法、】唯一不同的是 第八种枚举类型的使用。
在单例中要注意java对类装载机制概念的引入,饿汉式通过在类装载的时候进行了实例化,而懒汉模式的 lazy loading就做到了在调用获取对象方法的时候进行实例化。但是因为传统的懒汉模式有if判断会影响到线程的介入所以我们要考虑到线程安全的问题。
//============================================
//饿汉式(静态常量) 单例模式【第一种】
/**
* 优点:在类进行装载时完成实例化,避免线程同步问题;
* 缺点:没有达到 lazy loading 的效果,如果从始至终没有使用实例的话会造成内存浪费
*/
// private final static Teacher t1=new Teacher();
//
// private Teacher() {}
//
// public static Teacher getInteance() {
// return t1;
// }
//=============================================
//=============================================
//饿汉式(静态代码块)
// private static Teacher teacher;
// static {teacher=new Teacher();}
// private Teacher() {};
// public static Teacher getTeacher() {
// return teacher;
// }
//与饿汉式静态常亮一样就是在类装载时完成实例化
//优缺点同上只是由静态常量变成了静态代码块。
//=============================================
//=============================================
//懒汉式(线程不安全)【不可用】
// private static Teacher tr=null;
// public static Teacher gettTeacher() {
// if(tr==null) {
// tr=new Teacher();
// }
// return tr;
// }
// private Teacher() {};
//虽然完成了lazy loading的效果但是在单线程下是安全的 在多线程时会在if判断处产生多个实例,所以多线程不能使用。
//=============================================
//=============================================
//懒汉式(线程安全、同步方法)【不推荐用】
// private static Teacher teacher;
// private Teacher() {};
// public static synchronized Teacher getteTeacher() {
// if(teacher==null) {
// teacher=new Teacher();
// }
// return teacher;
// }
//完成了线程安全的lazy loading懒加载,但是效率太低,每个线程在想获得类的实例时,执行一次实例化后面的直接return 就可以
//方法同步效率过低需要改进。
//=============================================
//=============================================
//懒汉式(线程安全,同步代码块)[不可用]
// private static Teacher teacher;
// private Teacher () {};
// public static Teacher gettTeacher() {
// if(teacher==null) {
// synchronized (Teacher.class) {
// teacher=new Teacher();
// }
// }
// return teacher;
// }
//会面临线程不安全的特征 在判断时同样造成多实例化现象。
//=============================================
//=============================================
//双重检查
// private static Teacher teacher;
// private Teacher() {};
// public static Teacher getTeacher() {
// if(teacher==null) {
// synchronized(Teacher.class) {
// if(teacher==null) {
// teacher=new Teacher();
// }
// }
// }
// return teacher;
// }
//线程安全、延时加载;效率较高
//=============================================
// private Teacher() { };
// private static class InTeacher{
// private static final Teacher tr=new Teacher();
// }
// public static Teacher geTeacher() {
// return InTeacher.tr;
// }
//静态内部类方式在Teacher类被装载时不会立即实例化,而是在需要实例化时
//调用getTeacher方法,才会装载内部类,从此完成InTeacher的实例化
//=============================================
//=============================================
public enum TeacherEnum {
INSTANCE;
static Integer d1=1;
public void wheverMethod() {
d1++;
System.out.println("我的方法"+d1);
}
//JDK 1.5后才添加的单例实现模式,不仅能避免多线程同步问题,还可以防止
//反序列化重新创建新的对象。可能是因为枚举类型在JDK1.5中才
//系统内存中该类只存在一个对象,节省系统资源,对于一些需要频繁创建销毁的对象,使用单例模式可以提高系统性能。
}
//=============================================
还有测试单例模式线程安全的demo
public static void main(String[] args) {
CountDownLatch latch = new CountDownLatch(100);
for(int i=0;i<100;i++) {
new Thread() {
public void run() {
Teacher s1=Teacher.getTeacher();
System.out.println("线程名字:"+getName()+",结果"+(s1==Teacher.getTeacher()));
}
}.start();
latch.countDown();
}
try {
latch.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}