单例模式的几种写法
Posted 萌妹子_liu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式的几种写法相关的知识,希望对你有一定的参考价值。
1、静态初始化
/**
- 饿汉式
- 类加载到内存后,就实例化一个单例,jvm保证线程安全
- 简单实用,推荐使用
- 唯一缺点:不管用到与否,类加载时就完成实例化
- (话说你不用的,你转载它干啥)
- 一般这种就够用了
*/
public class Mgr01 {
private static final Mgr01 INSTANCE = new Mgr01();
private Mgr01(){}
public static Mgr01 getInstance(){return INSTANCE; }
public void m(){
System.out.println("m");
}
public static void main(String[] args){
Mgr01 m1 = Mgr01.getInstance();
Mgr01 m2 = Mgr01.getInstance();
System.out.println(m1 == m2);
}
}
//这种写法跟Mgr01一个意思
public class Mgr02 {
private static final Mgr02 INSTANCE;
static {
INSTANCE = new Mgr02();
}
private Mgr02(){}
public static Mgr02 getInstance(){return INSTANCE;}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
Mgr02 m1 = Mgr02.getInstance();
Mgr02 m2 = Mgr02.getInstance();
System.out.println(m1 == m2);
}
}
2、加锁+双重检查~~~~
/**
- lazy loading
- 也称懒汉式
- 虽然达到了按需初始化的目的,但是带来线程不安全问题
- 可以通过synchronize解决,这个是可以正常使用的,但也带来效率下降问题
*/
public class Mgr04 {
private static volatile Mgr04 INSTANCE;
private Mgr04() {
}
//这个synchronized锁定的是Mgr04.class,因为锁是加在static上面的
public static synchronized Mgr04 getInstance(){
if(INSTANCE == null){
try {
Thread.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new Mgr04();
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Mgr04.getInstance().hashCode());
}).start();
}
}
}
/**
- lazy loading
- 也称懒汉式
- 虽然达到了按需初始化的目的,但是带来线程不安全问题
- 可以通过synchronize解决,这个是可以正常使用的,但也带来效率下降
- 这是一种完美写法
*
*/
public class Mgr06 {
private static volatile Mgr06 INSTANCE;
private Mgr06() {
}
public static Mgr06 getInstance(){
if(INSTANCE == null){
//双重检查
synchronized(Mgr06.class){
if(INSTANCE == null){
try {
Thread.sleep(1);
}catch (InterruptedException e){
e.printStackTrace();
}
INSTANCE = new Mgr06();
}
}
}
return INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(Mgr06.getInstance().hashCode());
}).start();
}
}
}
3、静态内部类方式
/**
- 静态内部类方式
- JVM保证单例
- 胜在静态的东西只加载一次,并且加载外部类时不会加载内部类,这样可以实现懒加载
- 比Mgr01完美,
*/
public class Mgr07 {
private Mgr07(){}
private static class Mgr07Holder{
private final static Mgr07 INSTANCE = new Mgr07();
}
public static Mgr07 getInstance(){
return Mgr07Holder.INSTANCE;
}
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
for(int i = 0; i< 100; i++){
new Thread(()->{
System.out.println(Mgr07
.getInstance().hashCode());
}).start();
}
}
}
4、枚举形式
/**
- 不仅可以解决线程同步,还可以防止反序列化
*/
public enum Mgr08 {
INSTANCE;
public void m(){}~~~~
public static void main(String[] args) {
for(int i = 0; i< 100; i++){
new Thread(()->{
System.out.println(Mgr08.INSTANCE.hashCode());
}).start();
}
}
}
以上是关于单例模式的几种写法的主要内容,如果未能解决你的问题,请参考以下文章