IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 设计模式之单例 -> 正文阅读

[Java知识库]设计模式之单例

概念:

? ? ? ??

采取一定的方式保证整个软件系统,对某个类只能存在一个对象实例该类提供一个取得对象实例方法

饿汉式(静态常量)


import java.io.File;
import java.io.IOException;


class Person{
    private final static Person instance = new Person();
    //私有化 构造 防止外部 new 对象
    private Person(){

    }
    //对外提供静态方法 获取对象
    public static Person Getinstance(){
        return instance;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }

}

这种方式优缺点

优点:这种方法比较简单,类装载的时候就完成实例化,避免线程同步问题

缺点:这种在类装载的时候完成初始化,如果是没有用到,则浪费内存,这种单例模式可以,但是可能浪费内存

饿汉式(静态代码块)

class Person{
    private  static Person instance;
    //私有化 构造 防止外部 new 对象
    private Person(){

    }
    static {
        instance = new Person();
    }
    //对外提供静态方法 获取对象
    public static Person Getinstance(){
        return instance;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }


}

这种方式和上面一种一样,可能造成内存浪费

懒汉式(线程不安全)

class Person{
    private  static Person instance;
    //私有化 构造 防止外部 new 对象
    private Person(){

    }
    //对外提供静态方法 获取对象
    public static Person Getinstance(){
        if(instance == null){
            instance = new Person();
        }
        return instance;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }
}

优缺点:线程不安全,不会浪费内存 如果在多线程下,一个线程进入if代码块 还未来得及往下执行,另一个线程 也通过了这个判断语句,这就会产生过个实例,所以多线程不可使用这个方式

懒汉式(线程安全,同步方法)


import java.io.File;
import java.io.IOException;


class Person{
    private  static Person instance;
    //私有化 构造 防止外部 new 对象
    private Person(){

    }
    //对外提供静态方法 获取对象 这样不会多个线程进入这个方法
    public synchronized static Person Getinstance(){
        if(instance == null){
            instance = new Person();
        }
        return instance;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }
}

这种方法虽然解决看 多线程问题,但是效率太低了 每次获取实例对象都要进行同步

双重检查

public class Person{
    private  static volatile Person instance;
    //私有化 构造 防止外部 new 对象
    private Person(){
        
    }
    //对外提供静态方法 
    public static Person Getinstance(){
        if (instance == null){
            synchronized (Person.class){
                if(instance == null){
                    instance = new Person();
                }
            }
        }
        return instance;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }
}

我们进行两次判断检查 这样可以保证线程安全,这样实例代码就执行了一次 后面访问时 判断 是否为空 直接return 实例化对象 也避免的反复进行方法同步 线程安全 延迟加载 效率较高

静态内部类



import java.io.File;
import java.io.IOException;


class Person{
    private static volatile Person INSTANCE;
    //私有化 构造 防止外部 new 对象
    private Person(){

    }
    //静态内部类
    private static class PersionInstance{
        private static final Person INSTANCE = new Person();
    }
    public static Person Getinstance(){

        return PersionInstance.INSTANCE;
    }
}

public class MainApp {
    public static void main(String[] args) {
        Person getinstance = Person.Getinstance();
        Person getinstance1 = Person.Getinstance();
        System.out.println(getinstance == getinstance1);//true
    }
}

这种方式 采用类装载的机制保证实例化只有一个线程 静态内部类被装载不会立刻实例化 而是在需要的时候 调用getinstace方法 才会装载静态内部类 而完成Person实例化 类的静态属性只会在第一次加载类的时候初始化 在这里jvm帮助我们保证线程的安全 在类的初始化 别的线程无法进入 避免线程的不安全 利用 静态内部类特点实现延迟加载 效率高

枚举方法实现单例

enum Person{
    INSTANCE;//属性
    public void sayok(){
        System.out.println("ok");
    }
}
public class MainApp {
    public static void main(String[] args) {
        Person instance1 =  Person.INSTANCE;
        Person instance2 =  Person.INSTANCE;
        System.out.println(instance1 == instance2);
    }
}

避免多线程同步,防止反序列化

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 15:48:10  更:2021-12-14 15:49:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 5:25:23-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码