单例模式,保证对象只创建一次,减少内存的消耗,重用,关键词构造私有化
1.饿汉模式,启动程序时就初始化对象,这样的情况就是很占用内存,类似于你启动游戏有多个地图,不是根据你选择什么地图进行加载,而是启动时就将所有地图都加载,这种情况就很慢很耗内存。
package com.example.demo.single;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* @author Mikey
* @version 1.0
* @date 2023/2/10 10:39
* @description 单例模式--饿汉模式
*/
public class Singleton_1 {
private static Singleton_1 instance = new Singleton_1();
private Singleton_1(){
}
public static Singleton_1 getInstance(){
return instance;
}
public static void main(String[] args) {
List<CompletableFuture<Singleton_1>> list = new ArrayList<>();
int len = 100;
for (int i = 0; i < len; i++) {
// 多线程调用,看结果获取到的是否为同一实例
CompletableFuture<Singleton_1> future = CompletableFuture.supplyAsync(() -> {
Singleton_1 in1 = Singleton_1.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + in1);
return in1;
});
list.add(future);
}
System.out.println("合并开始------------");
CompletableFuture<Singleton_1>[] futures2 = list.toArray(new CompletableFuture[0]);
CompletableFuture.allOf(futures2).join();
System.out.println("----------执行完成");
}
}
2.内部类方式实现,这种写法比较简单,线程安全的,较为推荐
package com.example.demo.single;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
/**
* @author Mikey
* @version 1.0
* @date 2023/2/10 15:31
* @description 内部类方式实现
*/
public class Singleton_3 {
private volatile static Singleton_3 instance;
private Singleton_3(){
}
private static class SingleHandler{
private static Singleton_3 instance = new Singleton_3();
}
public static Singleton_3 getInstance(){
return Singleton_3.SingleHandler.instance;
}
public static void main(String[] args) {
List<CompletableFuture<Singleton_3>> list = new ArrayList<>();
int len = 100;
for (int i = 0; i < len; i++) {
// 多线程调用,看结果获取到的是否为同一实例
CompletableFuture<Singleton_3> future = CompletableFuture.supplyAsync(() -> {
Singleton_3 in1 = Singleton_3.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + in1);
return in1;
});
list.add(future);
}
System.out.println("合并开始------------");
CompletableFuture<Singleton_3>[] futures2 = list.toArray(new CompletableFuture[0]);
CompletableFuture.allOf(futures2).join();
System.out.println("----------执行完成");
}
}
3.懒汉模式(线程安全),本文展示的是方法内加锁,也称双检查加锁(较为推荐),还有一种是方法上加锁,相比于双检查加锁较为不推荐,每次访问函数都会有锁占用资源。
package com.example.demo.single;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Mikey
* @version 1.0
* @date 2023/2/10 11:11
* @description 懒汉模式
*/
public class Singleton_2 {
private static Singleton_2 instance;
private Singleton_2(){
}
// 线程安全
public static Singleton_2 getInstance() {
if (null != instance) return instance;
synchronized (Singleton_2.class) {
if(null == instance){
instance = new Singleton_2();
}
}
return instance;
}
public static void main(String[] args) {
// 1. 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<CompletableFuture<Singleton_2>> list = new ArrayList<>();
int len = 1000;
for (int i = 0; i < len; i++) {
// 多线程调用,看结果获取到的是否为同一实例
CompletableFuture<Singleton_2> future = CompletableFuture.supplyAsync(() -> {
Singleton_2 in1 = Singleton_2.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + in1);
return in1;
}, executorService);
list.add(future);
}
System.out.println("合并开始------------");
CompletableFuture<Singleton_2>[] futures2 = list.toArray(new CompletableFuture[0]);
CompletableFuture.allOf(futures2).join();
System.out.println("----------执行完成");
}
}
4.懒汉模式(线程不安全)
package com.example.demo.single;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @author Mikey
* @version 1.0
* @date 2023/2/10 15:55
* @description 懒汉模式线程不安全
*
*/
public class Singleton_4 {
private static Singleton_4 instance;
private Singleton_4(){
}
public static Singleton_4 getInstance(){
if(null == instance){
instance = new Singleton_4();
}
return instance;
}
public static void main(String[] args){
// 1. 创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<CompletableFuture<Singleton_4>> list = new ArrayList<>();
int len = 50;
for (int i = 0; i < len; i++) {
// 多线程调用,看结果获取到的是否为同一实例
CompletableFuture<Singleton_4> future = CompletableFuture.supplyAsync(() -> {
Singleton_4 in1 = Singleton_4.getInstance();
System.out.println(Thread.currentThread().getName() + ":" + in1);
return in1;
}, executorService);
list.add(future);
}
System.out.println("合并开始------------");
CompletableFuture<Singleton_4>[] futures2 = list.toArray(new CompletableFuture[0]);
CompletableFuture.allOf(futures2).join();
System.out.println("----------执行完成");
}
}
这种模式建议用debugger方式启动,比较容易复现线程不安全的场景