利用static来实现单例模式
一:之前旧的写法
class Singleton{
private Singleton() {}
private static Singleton instance = null;
public synchronized static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
就利用Sington.getInstace就可以了,获得的是同一个实例。上面那个代码有两个优点:
- 懒加载,把在堆创建实例这个行为延迟到类的使用时。
- 锁效果,防止生成多个实例,因为synchronized修饰这个static方法,所以相当于给这个方法加上了一个类锁。
二:static代码块的效果
先来看一段代码:
class StaticClass{
private static int a = 1;
static{
System.out.println("语句1");
System.out.println("语句2");
}
static{
System.out.println("语句3");
System.out.println("语句4");
}
}
当在多个线程同时触发类的初始化过程的时候(在初始化过程,类的static变量会被赋值为JVM默认值并且static代码块会被执行),为什么static不会被多次执行?因为有可能两个线程同时检测到类还没被初始化,然后都执行static代码块,结果就把语句1234多打印了,为什么上述情况不会发生。
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
try {
Class.forName("StaticClass");//这一行触发类的初始化导致静态代码块执行
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
thread1.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
try {
Class.forName("StaticClass");//同样
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
});
thread2.start();
结果如下:
语句1
语句2
语句3
语句4
有一段英文对其进行了解释:
static initialization block can be triggered from multiple parallel threads (when the loading of the class happens in the first time), Java runtime guarantees that it will be executed only once and in thread-safe manner + when we have more than 1 static block - it guarantees the sequential execution of the blocks, 也就是说,java runtime帮我们做了两件事:
- 在并行线程中,都出现了第一次初始化类的情况,保证类的初始化只执行一次。
- 保证static代码块的顺序执行
三:单例的另一种写法
有了对static的知识的了解之后,我们可以写出这样的单例模式:
class Singleton{
private Singleton() {}
private static class NestedClass{
static Singleton instance = new Singleton();//这条赋值语句会在初始化时才运行
}
public static Singleton getInstance() {
return NestedClass.instance;
}
}
- 懒加载,因为static语句会在初始化时才赋值运行,达到了懒加载的效果。
- 锁的效果由Java runtime保证,虚拟机帮我们保证static语句在初始化时只会执行一次。
四:总结
如果不知道static的基础知识和虚拟机类加载的知识,我可能并不会知道这一种方法。理论永远先行于技术,要学好理论才能从根本上提升自己。
本博文站在以下这位巨人的肩膀上:https://www.linkedin.com/pulse/static-variables-methods-java-where-jvm-stores-them-kotlin-malisciuc
利用static来实现单例模式的更多相关文章
- JAVA Static方法与单例模式的理解
近期用sonar測评代码质量的时候,发现一个问题,project中一些util类,曾经写的static方法都提示最好用单例的方式进行改正. 为此,我细致想了想,发现还是非常有道理的.这里谈谈我个人对s ...
- JDK设计模式之—单例模式和static关键字
首先了解static 关键字 static声明的方法是静态方法,static声明的成员变量为静态成员变量.对于该类的所有对象来说,static的成员变量和static只有一份存储空间 即使没有创建该类 ...
- Java——static关键字
前言 static关键字算是Java中比较复杂的关键字之一,它可以修饰变量.方法.类以及代码块.下面将介绍static的具体使用. static引入的目的 static的作用 static修饰变量 s ...
- iOS下单例模式实现(二)利用宏定义快速实现
在上一节里提到了用利用gcd快速实现单例模式. 一个项目里面可能有好几个类都需要实现单例模式.为了更高效的编码,可以利用c语言中宏定义来实现. 新建一个Singleton.h的头文件. // @int ...
- 23种设计模式--单例模式-Singleton
一.单例模式的介绍 单例模式简单说就是掌握系统的至高点,在程序中只实例化一次,这样就是单例模式,在系统比如说你是该系统的登录的第多少人,还有数据库的连接池等地方会使用,单例模式是最简单,最常用的模式之 ...
- 【白话设计模式四】单例模式(Singleton)
转自:https://my.oschina.net/xianggao/blog/616385 0 系列目录 白话设计模式 工厂模式 单例模式 [白话设计模式一]简单工厂模式(Simple Factor ...
- 设计模式(4) -- 单例模式(Singleton)
设计模式(4) -- 单例模式(Singleton) 试想一个读取配置文件的需求,创建完读取类后通过New一个类的实例来读取配置文件的内容,在系统运行期间,系统中会存在很多个该类的实例对象,也就是说 ...
- Java设计模式-单例模式及线程安全问题
单例模式是非常常用的设计模式,他确保了一个类只有一个对象,并且这个对象是自己创建的,外界可以获取使用到这个对象. 单例模式一般有两种:懒汉式,饿汉式(其实还有一种登记式,把创建的对象放在map集合中, ...
- 单例模式的优化之路(java)
1.概述 最近在优化公司以前老项目的代码时,发现有些类的代码频繁地创建和销毁对象,资源消耗比较严重.针对这些做了一些优化,改用单例模式,避免频繁的创建和销毁对象,说起单例模式,相信每个人都会写,接下来 ...
随机推荐
- Centos 常用指令
1.*.tar 用 tar xvf 解压 2.*.gz 用 gzip d或者gunzip 解压 3.*.tar.gz和*.tgz 用 tar xzf 解压 4.*.bz2 用 bzip2 d或者用 ...
- matplotlib 坐标轴刻度能见度问题
matplotlib 画图时如果图像太大就会挡住了坐标轴,刻度就看不到了.可以利用zorder设置level,level越小越先绘制. 例子: 1 import matplotlib.pyplot a ...
- C++STL标准库学习笔记(三)multiset
C++STL标准库学习笔记(三)multiset STL中的平衡二叉树数据结构 前言: 在这个笔记中,我把大多数代码都加了注释,我的一些想法和注解用蓝色字体标记了出来,重点和需要关注的地方用红色字体标 ...
- shell脚本 系统状态信息查看
一.简介 源码地址 日期:2018/6/23 介绍:显示简单的系统信息 效果图: 二.使用 适用:centos6+,ubuntu12+ 语言:中文 注意:无 下载 wget https://raw.g ...
- dart系列之:实时通讯,在浏览器中使用WebSockets
目录 简介 dart:html中的WebSockets 创建一个WebSocket WebSocket的状态 发送消息 处理WebSocket事件 总结 简介 web客户端和服务器端通信有两种方式,一 ...
- redis pipeset发布订阅
#!/usr/bin/env python # Author:Zhangmingda import redis,time pool = redis.ConnectionPool(host='192.1 ...
- outlook2007邮件里的图片显示不出来
outlook2007邮件里的图片显示不出来,这是为啥? 以图片为附件的形式进行传送吧,这样在收件箱里就能在线看图片了,不用担心看不到图片
- github fmt库语法+范例(fmt version :7.0.1)
!!版权声明:本文为博主原创文章,版权归原文作者和博客园共有,谢绝任何形式的 转载!! 作者:mohist fmt fmt 源码: https://github.com/fmtlib/fmt 本文翻译 ...
- Visual Studio之__cplusplus版本
1. 默认值 Visual Studio(下文简称VS)中__cplusplus宏的默认值一直是: 199711L 可以用下面的代码查看 __cplusplus 的输出结果: #pragma once ...
- 【LeetCode】264. Ugly Number II 解题报告(Java & Python)
标签(空格分隔): LeetCode 作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ https://leetcode.com/prob ...