单例模式
应用场景:在内存中只有一个实例,如xxxFactory,xxxMgr
有八种单例,完美无缺的有两种,常用的却并非这两种
1、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 8:35
* 饿汉式
* 类加载到内存后,只有一个实例,JVM保证线程安全
* 简单使用,推荐实用
* 唯一缺点:不管用到与否,类装载时就完成实例化
* (话说你不用它,装在它干嘛)
*/
public class Mgr1 {
// JVM保证每个class只能load进内存一次,static变量是class load完马上初始化的,保证只能初始化一次
private static final Mgr1 INSTANCE = new Mgr1();
private Mgr1(){};// 最关键,其他类无法new
public static Mgr1 getInstance(){return INSTANCE;};
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
Mgr1 mgr11 = Mgr1.getInstance();
Mgr1 mgr12 = Mgr1.getInstance();
System.out.println(mgr11 == mgr12);
}
}
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 8:35
*/
public class Main {
public static void main(String[] args) {
// new Mgr1();new不出来怎么办?只能
Mgr1 mgr1 = Mgr1.getInstance();
}
}
2、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 8:59
* 与Mgr1类似
*/
public class Mgr2 {
// JVM保证每个class只能load进内存一次,static变量是class load完马上初始化的,保证只能初始化一次
private static final Mgr2 INSTANCE;
static {
INSTANCE = new Mgr2();
}
private Mgr2(){};// 最关键,其他类无法new
public static Mgr2 getInstance(){return INSTANCE;};
public void m(){
System.out.println("m");
}
public static void main(String[] args) {
Mgr2 mgr21 = Mgr2.getInstance();
Mgr2 mgr22 = Mgr2.getInstance();
System.out.println(mgr21 == mgr22);
}
}
3、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 9:04
* lazy loading
* 也称懒汉式
* 虽然达到了按需初始化的目的,但却带来了多线程失效的问题
*/
public class Mgr3 {
private static Mgr3 INSTANCE;//最开始不初始化
private Mgr3(){};// 同样的私有构造
public static Mgr3 getInstance() {
if (INSTANCE == null) { // 这里有线程问题
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr3(); // 需要的时候初始化
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(()->{
System.out.println(Mgr3.getInstance().hashCode());
}).start();
}
}
}
4、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 9:24
* 加锁优化了Mgr3,却带来了效率低下的问题
*/
public class Mgr4 {
private static Mgr4 INSTANCE;//最开始不初始化
private Mgr4(){};// 同样的私有构造
public synchronized static Mgr4 getInstance() {
if (INSTANCE == null) { // 这里有线程问题
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr4(); // 需要的时候初始化
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(()->{
System.out.println(Mgr4.getInstance().hashCode());// 同一个类的不同对象hash码不同
}).start();
}
}
}
5、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 9:29
* Mgr4的基础上减少锁住的代码量,然而不可行
*/
public class Mgr5 {
private static Mgr5 INSTANCE;//最开始不初始化
private Mgr5(){};// 同样的私有构造
public static Mgr5 getInstance() {
if (INSTANCE == null) { // 这里有线程问题
synchronized(Mgr5.class){// 需要时加锁,试图减少锁住的代码量,然而不可行
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
INSTANCE = new Mgr5(); // 需要的时候初始化
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(()->{
System.out.println(Mgr5.getInstance().hashCode());// 同一个类的不同对象hash码不同
}).start();
}
}
}
6、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 9:40
* 双检索,曾经是单例的完美的方案
*/
public class Mgr6 {
private static Mgr6 INSTANCE;//最开始不初始化
private Mgr6(){};// 同样的私有构造
public static Mgr6 getInstance() {
if (INSTANCE == null) { // 这里有线程问题
// 双检锁
synchronized (Mgr6.class) {
if (INSTANCE == null) {
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
INSTANCE = new Mgr6(); // 需要的时候初始化
}
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(()->{
System.out.println(Mgr6.getInstance().hashCode());// 同一个类的不同对象hash码不同
}).start();
}
}
}
7、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 9:48
* 静态内部类方式
* JVM保证单例
* 加载外部类时不会加载内部类
* 一种完美方案
*/
public class Mgr7 {
private Mgr7(){}
private static class Mgr7Holder {// private 修饰保证外部访问不了
private final static Mgr7 INSTANCE = new Mgr7();// 内部类可以访问外部类私有
}
public static Mgr7 getInstance() {
return Mgr7Holder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(() -> {
System.out.println(Mgr7.getInstance().hashCode());
}).start();
}
}
}
8、
package org.ali.singleton;
/**
* Author: lury
* Date: 2022-09-04 10:04
* 不仅可以解决线程同步,还可以防止反序列化
* 也是完美的 perfect
* effective java 作者创作的
*/
public enum Mgr8 {
INSTANCE;
public static void main(String[] args) {
for (int i = 0;i < 100;i++) {
new Thread(() -> {
System.out.println(Mgr8.INSTANCE.hashCode());
}).start();
}
}
}
作者:万能包哥 出处:http://www.cnblogs.com/mybloger/ 本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。 如果文中有什么错误,欢迎指出。以免更多的人被误导。 |