Java23种设计模式之单例模式
一、单例模式简介
单例模式是Java设计模式中常见的一种模式。主要分为懒汉式单例、饿汉式单例、登记式单例;
单例模式的特点: 1、单例类只能有一个实例; 2、单例类必须自己创建自己的唯一的实例; 3、单例类必须给所有其他对象提供这一实例;
二、饿汉式单例
- public class SingleTonModel {
- private SingleTonModel(){}
- private static final SingleTonModel singt=new SingleTonModel();
- public static SingleTonModel getInstance(){
- return singt;
- }
- }
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以天生是线程安全的。
三、懒汉式单例
简单的例子:
- public class SingleTonModel {
- private SingleTonModel(){}
- private static SingleTonModel singt=null;
- public static SingleTonModel getInstance(){
- if(singt==null){
- singt=new SingleTonModel();
- }
- return singt;
- }
- }
(事实上,通过Java反射机制是能够实例化构造方法为private的类的,那基本上会使所有的Java单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)
但是以上懒汉式单例的实现没有考虑线程安全问题,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全:(课外知识可以了解线程安全)
改造一:在静态方法上添加关键词:synchronized,进行同步
- public class SingleTonModel {
- private SingleTonModel(){}
- private static SingleTonModel singt=null;
- public static synchronized SingleTonModel getInstance(){
- if(singt==null){
- singt=new SingleTonModel();
- }
- return singt;
- }
- }
虽然通过同步保障了线程安全,但是每次都要同步,会影响性能,毕竟99%的情况下是不需要同步的。
改造二:在判断不存在实例时才进行同步
- public class SingleTonModel {
- private SingleTonModel(){}
- private static SingleTonModel singt=null;
- public static SingleTonModel getInstance(){
- if(singt==null){
- synchronized(SingleTonModel.class){
- if(singt==null){
- singt=new SingleTonModel();
- }
- }
- }
- return singt;
- }
- }
在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。
改造三:添加内部静态类
- public class SingleTonModel {
- private SingleTonModel(){}
- private static class lanSingleton{
- private static final SingleTonModel singt=new SingleTonModel();
- }
- public static final SingleTonModel getInstance(){
- return lanSingleton.singt;
- }
- }
利用了classloader的机制来保证初始化instance时只有一个线程,所以也是线程安全的,同时没有性能损耗,所以一般我倾向于使用这一种。
四、登记式单例(很少用)
- /类似Spring里面的方法,将类名注册,下次从里面直接获取。
- public class Singleton3 {
- private static Map<String,Singleton3> map = new HashMap<String,Singleton3>();
- static{
- Singleton3 single = new Singleton3();
- map.put(single.getClass().getName(), single);
- }
- //保护的默认构造子
- protected Singleton3(){}
- //静态工厂方法,返还此类惟一的实例
- public static Singleton3 getInstance(String name) {
- if(name == null) {
- name = Singleton3.class.getName();
- System.out.println("name == null"+"--->name="+name);
- }
- if(map.get(name) == null) {
- try {
- map.put(name, (Singleton3) Class.forName(name).newInstance());
- } catch (InstantiationException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- }
- }
- return map.get(name);
- }
- //一个示意性的商业方法
- public String about() {
- return "Hello, I am RegSingleton.";
- }
- public static void main(String[] args) {
- Singleton3 single3 = Singleton3.getInstance(null);
- System.out.println(single3.about());
- }
- }
登记式单例实际上维护了一组单例类的实例,将这些实例存放在一个Map(登记薄)中,对于已经登记过的实例,则从Map直接返回,对于没有登记的,则先登记,然后返回。
课外小知识:
1、什么是线程安全
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
Java23种设计模式之单例模式的更多相关文章
- java23种设计模式之一: 单例模式(Singleton Pattern)
单例模式(Singleton Pattern)是设计模式中比较常用的一种,下面来总结单例模式的知识,包括: 1.理解什么是单例模式.单例模式有什么优点/缺点.单例模式的应用场景: 2.再来看看Java ...
- java23种设计模式——四、原型模式
源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...
- java23种设计模式—— 一、设计模式介绍
Java23种设计模式全解析 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模 ...
- java23种设计模式——五、建造者模式
源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式- ...
- java23种设计模式——八、组合模式
目录 java23种设计模式-- 一.设计模式介绍 java23种设计模式-- 二.单例模式 java23种设计模式--三.工厂模式 java23种设计模式--四.原型模式 java23种设计模式-- ...
- java23种设计模式——七、桥接模式
原文地址:https://www.cnblogs.com/chenssy/p/3317866.html 源码在我的github和gitee中获取 目录 java23种设计模式-- 一.设计模式介绍 j ...
- java23种设计模式 (转)
文章在:http://www.cnblogs.com/maowang1991/archive/2013/04/15/3023236.html 随着自己的开发经验增加以及自己做了很多的 大专栏 jav ...
- java23种设计模式详解(转)
设计模式(Design Patterns) ——可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- 学习java23种设计模式自我总结
首先先做个广告,以前看过@maowang 这位大神转的Java开发中的23种设计模式详解(转) ,但是看了之后都忘差不多了, 所以,开个帖子边学习边自我总结(纯手敲).一直以来像这种需要长久的运动,真 ...
随机推荐
- (转载)php循环检测目录是否存在并创建(循环创建目录)
(转载)http://www.jb51.net/article/25917.htm php循环检测目录是否存在并创建,需要的朋友可以参考下. 循环创建目录方法 这个会生成image.gif目录 代码如 ...
- Devexpress 之gridControl
1.gridControl如何去掉主面板? 鼠标右键Run Designer=>OptionsView => ShowGroupPanel=False: 2.gridControl如何设置 ...
- ARM学习笔记3——数据处理指令
一.数据处理指令概述 1.概念 数据处理指令是指对存放在寄存器中的数据进行处理的指令.主要包括算术指令.逻辑指令.比较与测试指令以及乘法指令 如果在数据处理指令前使用S前缀,指令的执行结果将会影响CP ...
- 作品第二课----点击DIV显示其内容
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- [Ruby on Rails Issue] When Setting Sqlite version on the Gemfile, Show error "An error occurred while installing sqlite3 ",
Issue: Gem files will remain installed in /tmp/bundler20140825-31835-p0c0p/sqlite3-1.3.9/gems/sqlite ...
- dd usb 启动盘制作 成功版本
在linux系统中,使用dd命令制作启动盘成功.方法是在终端中输入命令: dd if=/root/opensuse.iso of=/dev/sdb bs=4M 说明: 1.o ...
- nyoj 483 Nightmare【bfs+优先队列】
Nightmare 时间限制:1000 ms | 内存限制:65535 KB 难度:4 描述 Ignatius had a nightmare last night. He found him ...
- [学习笔记]设计模式之Abstract Factory
写在前面 为方便读者,本文已添加至索引: 设计模式 学习笔记索引 在上篇笔记Builder设计模式中,时の魔导士祭出了自己的WorldCreator.尽管它因此能创造出一个有山有树有房子的世界,但是白 ...
- tar linux 打包 压缩 gzip 命令说明
参数:-c :建立一个压缩档案的参数指令(create 的意思):-x :解开一个压缩档案的参数指令!-t :查看 tarfile 里面的档案! 特别注意,在参数的下达中, c/x/t ...
- URAL 1146 Maximum Sum(最大子矩阵的和 DP)
Maximum Sum 大意:给你一个n*n的矩阵,求最大的子矩阵的和是多少. 思路:最開始我想的是预处理矩阵,遍历子矩阵的端点,发现复杂度是O(n^4).就不知道该怎么办了.问了一下,是压缩矩阵,转 ...