设计模式与Java语言特性

本文围绕Java展开,介绍了单例、工厂、代理等设计模式,如单例模式的静态初始化、双检锁等实现方式;还阐述了Java版本特性,如1.8 Metaspace替换PremGen;同时讲解了对象引用、进程和线程间通信等知识,以及HashMap等集合类的相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 单例模式【1】:

    1. 静态初始化(饿汉).不管是否使用都会创建

饿汉demo
饿汉单例

     <tip1【2】>final:对于基本类型数据,final会将值变为一个常数(创建后不能被修改);但是对于对象句柄(亦可称作引用或者指针),final会将句柄变为一个常数(进行声明时,必须将句柄初始化到一个具体的对象。而且不能再将句柄指向另一个对象。static:修饰的属性强调它们只有一个。


    2. 双检锁(懒汉).单例变量必须要用volatile修饰.

懒汉demo
懒汉单例

 <tip2【3】>Java 语言提供了 volatile 和 synchronized 两个关键字来保证线程之间操作的有序性,volatile 是因为其本身包含“禁止指令重排序”的语义,synchronized 是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的,此规则决定了持有同一个对象锁的两个同步块只能串行执行。

登记式:

// 登记式
public class Singleton {
    private Singleton() {}
    public static Singleton getInstance() {
        return Holder.SINGLETON;
    }
    private static class Holder {
        private static final Singleton SINGLETON = new Singleton();
    }
}


    3. 单例注册表.spring中bean的单例模式就是用该方法实现.【4】

private final static Map<String, Object> singletonObjects = new ConcurrentHashMap<String, Object>(64);

Spring 对 Bean 实例的创建是采用单例注册表的方式进行实现的,而这个注册表的缓存是 ConcurrentHashMap 【5】对象。

 

  • 工厂模式:

        spring中的bean都是由不同工厂类创建的.【6,7】

        <扩展知识【8】>FactoryBean:是一个Java Bean,但是它是一个能生产对象的工厂Bean,它的实现和工厂模式及修饰器模式很像。比如下:我们把bean比作是人,那么FactoryBean可以算是一个女人,首先它本身也是一个人,但它能够生产人。BeanFactory:这就是一个Factory,是一个IOC容器或者叫对象工厂,它里面存着很多的bean。还用上面那个比如:如果bean是人,那么它可以理解成学校,学校里面很多人,学校管理这么多的人。

        <扩展知识【9】>​​​FactoryBean的使用场景:这个时候我们想到用FactoryBean来解决这个场景的问题,FactoryBean 通常是用来创建比较复杂的bean,一般的bean 直接用xml配置即可,但如果一个bean的创建过程中涉及到很多其他的bean 和复杂的逻辑,用xml配置比较困难,这时可以考虑用FactoryBean。

 

  • 代理模式:

        与中介者、外观区别:代理强调不直接引用一个对象,并实现和委托类相同的接口;中介者强调对象之间的通信解耦;外观强调添加职责。

        <扩展知识【10】>jdk动态代理、cglib动态代理

        <扩展知识【11】>javassist实现动态代理

 

  • 责任链模式:

       <扩展知识【12】>NIO、Netty

 

  • 构造器模式【13】:主要强调属性不可变

 

  • 集合类【14】:

        <tip1>HashMap的put方法的具体流程:

hashmap put方法

 

        <tip2>HashMap是使用了哪些方法来有效解决哈希冲突的:

                 1. 使用链地址法(使用散列表)来链接拥有相同hash值的数据;
                 2. 使用2次扰动函数(hash函数)来降低哈希冲突的概率,使得数据分布更平均;
                 3. 引入红黑树进一步降低遍历的时间复杂度,使得遍历更快;

        <tip3>HashMap多线程不安全的原因:1.7下扩容会有成环的风险【15】,1.7,1.8插入数据丢失,size函数不准确【16】

        <tip4>ConcurrentHashMap:CAS【17】

ConcurrentHashMap CAS流程

 

        <tip5>红黑树【18】

 

  • 动态代理、反射:【19】

 

  • 对象引用:对象引用存放在栈中,对象本身存放在堆中,多个对象引用可以指向同一个对象。

 

  • Java版本特性:

        1.8Metaspace替换PremGen【20】

 

  • Java中==与equals的区别【21】:

         “==” 比较的是两个引用在内存中指向的是不是同一对象(即同一内存空间),默认的实现只有当对象和自身进行比较时才会返回true, 这个时候和 “==”是等价的。Java中很多类(包装类、String类  Date类  File类)等都对equals方法进行了重写。

 

  • 对象引用:

        强引用、软引用、弱引用、虚引用【22】。

        深入理解JAVA虚拟机一书中有这样一句描述:“为一个对象设置虚引用关联的唯一目的就是能在这个对象被收集器回收时收到一个系统通知”。所以虚引用更多的是用于对象回收的监听,能做的功能如下:

  1. 重要对象回收监听 进行日志统计

  2. 系统gc监听 因为虚引用每次GC都会被回收,那么我们就可以通过虚引用来判断gc的频率,如果频率过大,内存使用可能存在问题,才导致了系统gc频繁调用

 

  • 进程和线程间通信:

        线程间通信【23】:1、共享变量;2、wait/notify机制;3、Lock/Condition机制;4、管道;

        进程间通信【24】:1、管道(PIPE) ;2、命名管道(FIFO); 3、信号量(Semphore) ;4、消息队列(MessageQueue) ;5、共享内存(SharedMemory); 6、 Socket;

Java进程间通信可以采用的办法:

Socket/RMI/WEBService/WebServer, 这些都可以实现直接的数据交换 
           Database/File, 这些可以实现间接的数据交换

Java NIO 来实现共享内存的办法就是让不同进程的内存映射文件关联到同一个物理文件,因为 MappedByteBuffer 能让内存与文件即时的同步内容。

 

  • Java中RuntimeException和Exception的区别【25】:非RuntimeException要自己写catch块处理掉。

 

 

参考链接:

【1】https://blog.51cto.com/13477015/2177185   《单例模式浅谈 ——饿汉式及懒汉式的Java实现》

【2】https://blog.youkuaiyun.com/qq1623267754/article/details/36190715  《Java中static、final、static final的区别》

【3】https://www.cnblogs.com/zhengbin/p/5654805.html   《Java中Volatile关键字详解》

【4】https://www.codercto.com/a/4924.html   《单例模式 - 单例注册表与 Spring 实现单例剖析》

【5】https://www.cnblogs.com/shan1393/p/9020564.html   《面试题:Concurrenthashmap原理分析 有用》

【6】https://blog.youkuaiyun.com/qq_35860138/article/details/88798726   《Spring中的bean的单例和多例》

【7】https://blog.youkuaiyun.com/magicianjun/article/details/78737840   《spring管理bean的三种创建方式》

【8】https://blog.youkuaiyun.com/u013185616/article/details/52335864/   《FactoryBean的实现原理与作用》

【9】https://blog.youkuaiyun.com/jiangzhexi/article/details/81072487   《FactoryBean是如何运用在我们程序中的》

【10】https://www.cnblogs.com/daniels/p/8242592.html   《设计模式---代理模式》

【11】https://www.jianshu.com/p/cec3e3e0627f   《Javassist 实现动态代理》

【12】https://www.jianshu.com/p/a4e03835921a   《《跟闪电侠学Netty》开篇:Netty是什么?》

【13】https://www.cnblogs.com/iCanhua/p/8636085.html   《Java设计模式系列 — 构造器模式》

【14】https://www.jianshu.com/p/939b8a672070   《Java集合必会14问(精选面试题整理)》

【15】https://www.jianshu.com/p/13c650a25ed3   《HashMap的ReHash图解》

【16】https://blog.youkuaiyun.com/fumitzuki/article/details/82760236   《HashMap多线程并发情况(JDK1.8)》

【17】https://www.cnblogs.com/junjiang3/p/8686290.html   《ConcurrentHashMap如何保证线程安全》

【18】http://www.360doc.com/content/18/0904/19/25944647_783893127.shtml   《五分钟搞懂什么是红黑树(全程图解)》

【19】https://baijiahao.baidu.com/s?id=1628782377871648532&wfr=spider&for=pc   《面试官:谈谈动态代理?》

【20】https://www.cnblogs.com/paddix/p/5309550.html   《Java8内存模型—永久代(PermGen)和元空间(Metaspace)》

【21】https://www.cnblogs.com/whcwkw1314/p/8044947.html   《Java中==与equals的区别及理解》

【22】https://www.cnblogs.com/blueskyli/p/9155106.html   《java对象的强引用,软引用,弱引用和虚引用》

【23】https://blog.youkuaiyun.com/ls5718/article/details/51878770   《JAVA线程与线程、进程与进程间通信》

【24】https://www.cnblogs.com/heyanan/p/7149755.html  《Java NIO进程间通信》

【25】https://www.cnblogs.com/cristin/p/7728409.html    《Java中RuntimeException和Exception的区别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值