java单例设计模式
什么是单例设计模式
单例即只有一个实例,该模式的作用是保证程序中某个类的对象只有一个。
单例模式分为懒汉式和饿汉式。
懒汉式
class Student{ static Student st; private Student(){} public static Student getInstance(){ //引用数据类型属性在内存中的默认值为null //如果值为null 只创建一次对象 if(st==null){ st = new Student(); } return st; } } public class Test1 { public static void main(String[] args) { // 利用hascode 相等 是单例 Student tes1 = Student.getInstance(); System.out.println(tes1.hashCode()); Student tes2 = Student.getInstance(); System.out.println(tes2.hashCode()); } }
以上可以看出结果的hasCode值是相同的只创建了一个对象
但是这种模式在多线程的情况下会产生线程安全问题:
class Teacher{ static Teacher s; private Teacher(){} public static Teacher getInstance(){ if(s == null){ s = new Teacher(); } return s; } } class StudentThread extends Thread{ public void run(){ for(int i = 0;i<3;i++){ Teacher ss = Teacher.getInstance(); System.out.println(ss.hashCode()); } } } public class Test2 { public static void main(String[] args) { //单例模式在多线程中存在线程安全问题 需要解决线程安全 //创建线程 StudentThread tt1 = new StudentThread(); StudentThread tt2 = new StudentThread(); //就绪状态 tt1.start(); tt2.start(); } }
如果在运行多次的情况下会出现hasCode不一定都一样 这就出现了线程安全问题:
解决办法只需要将返回对象的方法设置为同步方法即可
public synchronized static Teacher getInstance(){ if(s == null){ s = new Teacher(); } return s; }
饿汉式
//饿汉式 class Hangle{ //创建静态属性的时候就赋值 并且只执行一次 也就是说只创建一次对象 static Hangle ha = new Hangle(); public static Hangle getInstance(){ return ha; } } class SingleThread extends Thread{ public void run(){ for(int i = 0;i<4;i++){ Hangle hh = Hangle.ha; System.out.println(hh.hashCode()); } } } public class Test3 { public static void main(String[] args) { SingleThread tt1 = new SingleThread(); SingleThread tt2 = new SingleThread(); //就绪状态 tt1.start(); tt2.start(); // 总结: 懒汉式 在多线程环境中会发生线程安全问题 (可以解决线程问题) //而饿汉式不管是在单线程还是在多线程中 不存在线程安全问题 建议定义单例模式的话 用饿汉式 //饿汉式单例模式要比懒汉式效率高 } }