什么是单例设计模式
单例即只有一个实例, 该模式的作用是保证程序中某个类的对象只有一个.
单例模式分为懒汉式和饿汉式.
懒汉式
- 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();
- // 总结: 懒汉式 在多线程环境中会发生线程安全问题 (可以解决线程问题)
- // 而饿汉式不管是在单线程还是在多线程中 不存在线程安全问题 建议定义单例模式的话 用饿汉式
- // 饿汉式单例模式要比懒汉式效率高
- }
- }
来源: https://www.cnblogs.com/nianzhilian/p/9108589.html