java设计模式单例模式
创建型模式: – 单例模式、工厂模式、抽象工厂模式、建造者模式、原型模式。
• 结构型模式: – 适配器模式、桥接模式、装饰模式、组合模式、外观模式、享元模式、代理模 式。
• 行为型模式: – 模版方法模式、命令模式、迭代器模式、观察者模式、中介者模式、备忘录模 式、解释器模式、状态模式、策略模式、职责链模式、访问者模式
单例模式:
• 核心作用: – 保证一个类只有一个实例,并且提供一个访问该实例的全局访问点
• 常见应用场景:
– Windows的Task Manager(任务管理器)就是很典型的单例模式 – windows的Recycle Bin(回收站)也是典型的单例应用。在整个系统运行过程中,回收站一直维护着仅有的一个实例。
– 项目中,读取配置文件的类,一般也只有一个对象。没有必要每次使用配置文件数据,每次new一个对象去读取。
– 网站的计数器,一般也是采用单例模式实现,否则难以同步。
– 应用程序的日志应用,一般都何用单例模式实现,这一般是由于共享的日志文件一直处于打开状态,因为只能有一个实例去操作 ,否则内容不好追加。
– 数据库连接池的设计一般也是采用单例模式,因为数据库连接是一种数据库资源。
– 操作系统的文件系统,也是大的单例模式实现的具体例子,一个操作系统只能有一个文件系统。
– Application 也是单例的典型应用
– 在Spring中,每个Bean默认就是单例的,这样做的优点是Spring容器可以管理 – 在servlet编程中,每个Servlet也是单例 – 在spring MVC框架/struts1框架中,控制器对象也是单例
单例模式的优点:
– 由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要 比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动 时直接产生一个单例对象,然后永久驻留内存的方式来解决 – 单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计 一个单例类,负责所有数据表的映射处理
常见的五种单例模式实现方式:
– 主要: • 饿汉式(线程安全,调用效率高。 但是,不能延时加载。)
• 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
– 其他: • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用)
• 静态内部类式(线程安全,调用效率高。 但是,可以延时加载)
• 枚举单例(线程安全,调用效率高,不能延时加载)
饿汉式实现(单例对象立即加载)
//饿汉式单例
public class Singleton01 {
//类初始化时,立即加载这个对象
//加载类是天然的线程安全的,(没有延时加载的优势)
private static Singleton01 instance=new Singleton01();
private Singleton01(){ }
//方法没有同步,调用效率高
public static Singleton01 getInstance(){
return instance;
}
}
懒汉式
//懒汉式
public class Singleton02 {
//类初始化时,不初始化这个对象(真正用到的时候在创建)
private static Singleton02 instance;
private Singleton02(){ //私有构造器 }
//方法同步,调用效率低
public static synchronized Singleton02 getInstance(){
if(instance==null){
instance=new Singleton02();
}
return instance;
}
}
双重检索:
//双重检测所机制
//由于编译器优化原因和jvm底层内部模型原因,有时候回出现问题
public class Singleton03 {
private static Singleton03 instance=null; public static Singleton03 getInstance(){
if(instance==null){
Singleton03 sc;
synchronized (Singleton03.class){
sc=instance;
if(sc==null){
synchronized(Singleton03.class){
if(sc==null){
sc=new Singleton03();
}
}
instance=sc;
}
}
}
return instance;
}
private Singleton03(){ }
}
静态内部类:
//静态内部类
public class Singleton04 {
//要点:
//– 外部类没有static属性,则不会像饿汉式那样立即加载对象。
//– 只有真正调用getInstance(),才会加载静态内部类。加载类时是线程 安全的。
//instance是static final 类型,保证了内存中只有这样一个实例存在,而且只能被赋值一次,
//从而保证了线程安全性. – 兼备了并发高效调用和延迟加载的优势! private static class Singleton04ClassInstance {
private static final Singleton04 instance = new Singleton04();
}
private Singleton04() { }
public static Singleton04 getInstance() {
return Singleton04ClassInstance.instance;
}
}
枚举模式:
//枚举单例(没有延时加载)
public enum Singleton05 {
//定义一个枚举,枚举 元素本身就是一个单例
INSTANCE;
//添加自己需要的元素
public void singletonOperation(){ }
}
public static void main(String[] args) {
Singleton01 s1=Singleton01.getInstance();
Singleton01 s2=Singleton01.getInstance();
System.out.println(s1);
System.out.println(s2);
}

常见的五种单例模式实现方式
– 主要: • 饿汉式(线程安全,调用效率高。 但是,不能延时加载。) • 懒汉式(线程安全,调用效率不高。 但是,可以延时加载。)
– 其他: • 双重检测锁式(由于JVM底层内部模型原因,偶尔会出问题。不建议使用) • 静态内部类式(线程安全,调用效率高。 但是,可以延时加载) • 枚举式(线程安全,调用效率高,不能延时加载。并且可以天然的防止反射和反序列 化漏洞!) • 如何选用? – 单例对象 占用 资源 少,不需要 延时加载: • 枚举式 好于 饿汉式 – 单例对象 占用 资源 大,需要 延时加载: • 静态内部类式 好于 懒汉式
反射和序列化破坏单例:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor; public class SingletonTest01 {
public static void main(String[] args) throws Exception{
Singleton06 s1=Singleton06.getInstance();
Singleton06 s2=Singleton06.getInstance(); System.out.println(s1);
System.out.println(s2); //通过反射的方式直接调用私有构造器
Class<Singleton06> clazz= (Class<Singleton06>)Class.forName("demo.singleton.Singleton06");
//获取无参数构造器
Constructor<Singleton06> c=clazz.getDeclaredConstructor(null);
//跳过权限的检查
c.setAccessible(true);
Singleton06 s3=c.newInstance();
Singleton06 s4=c.newInstance(); System.out.println(s3);
System.out.println(s4); //通过序列化的方式构造多个对象
FileOutputStream fos=new FileOutputStream("d:/a.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/a.txt"));
Singleton06 s5=(Singleton06) ois.readObject();
System.out.println(s5);
}
}
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Constructor; public class SingletonTest01 {
public static void main(String[] args) throws Exception{
Singleton06 s1=Singleton06.getInstance();
Singleton06 s2=Singleton06.getInstance(); System.out.println(s1);
System.out.println(s2); //通过反射的方式直接调用私有构造器
Class<Singleton06> clazz= (Class<Singleton06>)Class.forName("demo.singleton.Singleton06");
//获取无参数构造器
Constructor<Singleton06> c=clazz.getDeclaredConstructor(null);
//跳过权限的检查
c.setAccessible(true);
Singleton06 s3=c.newInstance();
Singleton06 s4=c.newInstance(); System.out.println(s3);
System.out.println(s4); //通过序列化的方式构造多个对象
FileOutputStream fos=new FileOutputStream("d:/a.txt");
ObjectOutputStream oos=new ObjectOutputStream(fos);
oos.writeObject(s1);
oos.close();
fos.close(); ObjectInputStream ois=new ObjectInputStream(new FileInputStream("d:/a.txt"));
Singleton06 s5=(Singleton06) ois.readObject();
System.out.println(s5);
}
}
测试:
import java.util.concurrent.CountDownLatch;
public class SingletonTest03 {
public static void main(String[] args) throws Exception {
long start=System.currentTimeMillis();
int threanNum=10;
final CountDownLatch countDownLath=new CountDownLatch(threanNum);
for(int i=0;i<10;i++){
new Thread(new Runnable(){
@Override
public void run(){
for(int i=0;i<1000000;i++){
//Object o=Singleton04.getInstance();
Object o=Singleton05.INSTANCE;
}
countDownLath.countDown();
}
}).start();
}
countDownLath.await();//mian线程阻塞,知道计数器变成0,才会继续往下执行
long end=System.currentTimeMillis();
System.out.println("总耗时:"+(end-start));
}
}
多线程情况的下的单例模式:
//标准的单例模式
public class SingletonDemo {
private static volatile SingletonDemo instance=null;
private SingletonDemo(){
System.out.println(Thread.currentThread().getName()+
"\t 我是构造方法SingletonDemo()");
}
//双端检索机制
public static SingletonDemo getInstance(){
if(instance==null){
synchronized (SingletonDemo.class){
if(instance==null)
instance=new SingletonDemo();
}
}
return instance;
} public static void main(String[] args) {
for(int i=0;i<10;i++){
new Thread(()->{
SingletonDemo.getInstance();
},String.valueOf(i)).start();
}
}
}
java设计模式单例模式的更多相关文章
- java设计模式单例模式 ----懒汉式与饿汉式的区别
常用的五种单例模式实现方式 ——主要: 1.饿汉式(线程安全,调用率高,但是,不能延迟加载.) 2.懒汉式(线程安全,调用效率不高,可以延时加载.) ——其他: 1.双重检测锁式(由于JVM底层内部模 ...
- Java设计模式の单例模式
-------------------------------------------------- 目录 1.定义 2.常见的集中单例实现 a.饿汉式,线程安全 但效率比较低 b.单例模式的实现:饱 ...
- JAVA设计模式-单例模式(Singleton)线程安全与效率
一,前言 单例模式详细大家都已经非常熟悉了,在文章单例模式的八种写法比较中,对单例模式的概念以及使用场景都做了很不错的说明.请在阅读本文之前,阅读一下这篇文章,因为本文就是按照这篇文章中的八种单例模式 ...
- Java设计模式 - - 单例模式 装饰者模式
Java设计模式 单例模式 装饰者模式 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 静态代理模式:https://www.cnblogs.com/StanleyBlogs/p/1 ...
- 【设计模式】Java设计模式 - 单例模式
[设计模式]Java设计模式 - 单例模式 不断学习才是王道 继续踏上学习之路,学之分享笔记 总有一天我也能像各位大佬一样 分享学习心得,欢迎指正,大家一起学习成长! 原创作品,更多关注我CSDN: ...
- Java 设计模式 —— 单例模式
1. 概念: 单例模式是一种常用的软件设计模式.核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源.如果 ...
- Java设计模式 - 单例模式 (懒汉方式和饿汉方式)
概念: Java中单例模式是一种常见的设计模式,单例模式的意思就是只有一个实例.单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例.这个类称为单例类. 单例模式的写法有好几种,这 ...
- java设计模式——单例模式(一)
一. 定义与类型 定义:保证一个类仅有一个实例,并提供一个全局访问点 类型:创建型 二. 适用场景 想确保任何情况下都绝对只用一个实例 三. 优缺点 优点: 在内存里只有一个实例,减少了内存开销 可以 ...
- JAVA设计模式--单例模式
单例设计模式 Singleton是一种创建型模式,指某个类采用Singleton模式,则在这个类被创建后,只可能产生一个实例供外部访问,并且提供一个全局的访问点. 核心知识点如下: (1) 将采用单例 ...
- Java设计模式-单例模式(Singleton)
单例对象(Singleton)是一种常用的设计模式.在Java应用中,单例对象能保证在一个JVM中,该对象只有一个实例存在.这样的模式有几个好处: 1.某些类创建比较频繁,对于一些大型的对象,这是一笔 ...
随机推荐
- VUE-父组件和子组件
1.父组件 const cnp2 = Vue.extend({ template: ` <div> <h2>我是构造器2</h2> <cpn1>< ...
- Nginx+Docker部署模式下 asp.net core 获取真实的客户端ip
目录 Nginx+Docker部署模式下 asp.net core 获取真实的客户端ip 场景 过程还原 结论 参考资料 Nginx+Docker部署模式下 asp.net core 获取真实的客户端 ...
- Rust中的函数调用
注意区别语句和表达式哟. Rust是一门基于表示式的语言,牢记!!! fn main() { println!("Hello world!"); another_function( ...
- 使用Visual Studio学习C语言
注明:安装的是社区版,只写大部分步骤,做笔记之用.详细还需要看B站教程,https://www.bilibili.com/video/av59608520 一.安装软件 1.安装Visual Stud ...
- kali下ll命令无法使用
重装了系统之后,使用ll命令竟然发现报错了. bash: ll:未找到命令 果断解决一波: vim ~/.bashrc 将alias ll=’ls -l‘前面的注释符号#删掉 运行 问题完 ...
- 201871010124-王生涛 《面向对象程序设计(java)》第八周学习总结
博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...
- explain慢SQL分析解释
使用EXPLAIN关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是 如何处理你的SQL语句的.分析你的查询语句或是表结构的性能瓶颈. 使用方式:Explain+SQL语句 执行计划包含的信 ...
- LeetCode3-Longest_Substring_Without_Repeating_Characters
参考思路 https://github.com/azl397985856/leetcode/blob/master/problems/3.longestSubstringWithoutRepeatin ...
- mpich安装
1.简介与下载 MPICH是一种高性能的.可广泛移植的实现来自阿尔贡国家实验室的MPI-3.1标准. https://www.mpich.org/downloads/ 2.解压安装 tar xzvf ...
- 基于DFA算法、RegExp对象和vee-validate实现前端敏感词过滤
面临敏感词过滤的问题,最简单的方案就是对要检测的文本,遍历所有敏感词,逐个检测输入的文本是否包含指定的敏感词. 很明显上面这种实现方法的检测时间会随着敏感词库数量的增加而线性增加.系统会因此面临性能和 ...