–《菜鸟教程:单例模式》
单例模式 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 这种模式涉及到一个单一的类,该类负责创建自己的对象,同时确保只有单个对象被创建
普通单例模式
package cn.shentianlan.studytest.designmode.singleton;
/**
* @author 渊蓝
* @version 1.0
* @description 普通单例模式,在类加载时即初始化完成
* @date 2021/10/24 13:48
*/
public class GeneralSingleton {
private static GeneralSingleton generalSingleton = new GeneralSingleton();
private GeneralSingleton() {
}
public static GeneralSingleton getInstance(){
return generalSingleton;
}
}
懒汉式单例模式
package cn.shentianlan.studytest.designmode.singleton;
import java.util.concurrent.TimeUnit;
/**
* @author 渊蓝
* @version 1.0
* @description 懒加载单例模式(多线程下会存在问题)
* @date 2021/10/24 13:56
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if (lazySingleton==null){
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
多线程下懒汉式单例模式
package cn.shentianlan.studytest.designmode.singleton;
/**
* @author 渊蓝
* @version 1.0
* @description 多线程下使用双重检查加锁方式实现单例模式
* @date 2021/10/24 14:01
*/
public class LazyThreadSingleton {
/**
* volatile 确保当lazyThreadSingleton被实例化之后,所有线程都能及时读取到该实例
*/
private volatile static LazyThreadSingleton lazyThreadSingleton;
private LazyThreadSingleton(){}
public static LazyThreadSingleton getInstance(){
if (lazyThreadSingleton == null){
synchronized(LazyThreadSingleton.class){
if (lazyThreadSingleton==null){
lazyThreadSingleton = new LazyThreadSingleton();
}
}
}
return lazyThreadSingleton;
}
}
测试
为了能明显看到效果,在LazySingleton和LazyThreadSingleton创建实例时加上延时
package cn.shentianlan.studytest.designmode.singleton;
import java.util.concurrent.TimeUnit;
/**
* @author 渊蓝
* @version 1.0
* @description 懒加载单例模式(多线程下会存在问题)
* @date 2021/10/24 13:56
*/
public class LazySingleton {
private static LazySingleton lazySingleton;
private LazySingleton(){
}
public static LazySingleton getInstance() throws InterruptedException {
if (lazySingleton==null){
TimeUnit.MICROSECONDS.sleep(100);
lazySingleton = new LazySingleton();
}
return lazySingleton;
}
}
package cn.shentianlan.studytest.designmode.singleton;
import java.util.concurrent.TimeUnit;
/**
* @author 渊蓝
* @version 1.0
* @description 多线程下使用双重检查加锁方式实现单例模式
* @date 2021/10/24 14:01
*/
public class LazyThreadSingleton {
/**
* volatile 确保当lazyThreadSingleton被实例化之后,所有线程都能及时读取到该实例
*/
private volatile static LazyThreadSingleton lazyThreadSingleton;
private LazyThreadSingleton(){}
public static LazyThreadSingleton getInstance() throws InterruptedException {
if (lazyThreadSingleton == null){
TimeUnit.MICROSECONDS.sleep(100);
synchronized(LazyThreadSingleton.class){
if (lazyThreadSingleton==null){
lazyThreadSingleton = new LazyThreadSingleton();
}
}
}
return lazyThreadSingleton;
}
}
单元测试类
package cn.shentianlan.studytest.designmode.singleton;
import org.junit.Test;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
/**
* @author 渊蓝
* @version 1.0
* @description 单例模式测试类
* @date 2021/10/24 14:13
*/
public class SingletonTest {
@Test
public void generalSingletonTest() {
System.out.println("------------------generalSingletonTest----------------------------------");
GeneralSingleton generalSingleton1 = GeneralSingleton.getInstance();
GeneralSingleton generalSingleton2 = GeneralSingleton.getInstance();
System.out.println("generalSingleton1:" + generalSingleton1 + "--" + generalSingleton1.hashCode());
System.out.println("generalSingleton2:" + generalSingleton2 + "--" + generalSingleton2.hashCode());
System.out.println("generalSingleton1==generalSingleton2:" + (generalSingleton1 == generalSingleton2));
System.out.println();
}
/**
* 单线程懒加载测试
*/
@Test
public void lazySingletonTest() throws InterruptedException {
System.out.println("--------------------------lazySingletonTest:单线程懒加载测试------------------------------");
LazySingleton lazySingleton1 = LazySingleton.getInstance();
LazySingleton lazySingleton2 = LazySingleton.getInstance();
System.out.println("lazySingleton1:" + lazySingleton1 + "--" + lazySingleton1.hashCode());
System.out.println("lazySingleton2:" + lazySingleton2 + "--" + lazySingleton2.hashCode());
System.out.println("lazySingleton1==lazySingleton2:" + (lazySingleton1 == lazySingleton2));
System.out.println();
}
/**
* 多线性懒加载测试
* @throws InterruptedException
*/
@Test
public void multithreadedLazySingletonTest() throws InterruptedException {
System.out.println("--------------------------multithreadedLazySingletonTest:多线程懒加载测试------------------------------");
//线程数量
final int THREAD_NUMBER = 3;
CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);
//多线程下测试
for (int i = 0; i < THREAD_NUMBER; i++) {
new Thread(() -> {
LazySingleton lazySingleton = null;
try {
lazySingleton = LazySingleton.getInstance();
System.out.println(lazySingleton);
} catch (InterruptedException e) {
e.printStackTrace();
}
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println();
}
@Test
public void lazyThreadSingletonTest() throws InterruptedException {
System.out.println("-----------------------lazyThreadSingletonTest---------------------------------------");
LazyThreadSingleton lazyThreadSingleton1 = LazyThreadSingleton.getInstance();
LazyThreadSingleton lazyThreadSingleton2 = LazyThreadSingleton.getInstance();
System.out.println("lazyThreadSingleton1:" + lazyThreadSingleton1 + "--" + lazyThreadSingleton1.hashCode());
System.out.println("lazyThreadSingleton2:" + lazyThreadSingleton2 + "--" + lazyThreadSingleton2.hashCode());
System.out.println("lazyThreadSingleton1==lazyThreadSingleton2:" + (lazyThreadSingleton1 == lazyThreadSingleton2));
System.out.println();
}
@Test
public void multithreadedLazyThreadSingletonTest() throws InterruptedException {
System.out.println("-----------------------multithreadedLazyThreadSingletonTest---------------------------------------");
//线程数量
final int THREAD_NUMBER = 3;
CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUMBER);
//多线程下测试
for (int i = 0; i < THREAD_NUMBER; i++) {
new Thread(() -> {
LazyThreadSingleton lazySingleton = null;
try {
lazySingleton = LazyThreadSingleton.getInstance();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(lazySingleton);
countDownLatch.countDown();
}).start();
}
countDownLatch.await();
System.out.println();
}
}
执行结果:
--------------------------multithreadedLazySingletonTest:多线程懒加载测试------------------------------
cn.shentianlan.studytest.designmode.singleton.LazySingleton@19ca2465
cn.shentianlan.studytest.designmode.singleton.LazySingleton@61540d60
cn.shentianlan.studytest.designmode.singleton.LazySingleton@15864d5a
--------------------------lazySingletonTest:单线程懒加载测试------------------------------
lazySingleton1:cn.shentianlan.studytest.designmode.singleton.LazySingleton@15864d5a--361123162
lazySingleton2:cn.shentianlan.studytest.designmode.singleton.LazySingleton@15864d5a--361123162
lazySingleton1==lazySingleton2:true
-----------------------lazyThreadSingletonTest---------------------------------------
lazyThreadSingleton1:cn.shentianlan.studytest.designmode.singleton.LazyThreadSingleton@3c679bde--1013423070
lazyThreadSingleton2:cn.shentianlan.studytest.designmode.singleton.LazyThreadSingleton@3c679bde--1013423070
lazyThreadSingleton1==lazyThreadSingleton2:true
-----------------------multithreadedLazyThreadSingletonTest---------------------------------------
cn.shentianlan.studytest.designmode.singleton.LazyThreadSingleton@3c679bde
cn.shentianlan.studytest.designmode.singleton.LazyThreadSingleton@3c679bde
cn.shentianlan.studytest.designmode.singleton.LazyThreadSingleton@3c679bde
------------------generalSingletonTest----------------------------------
generalSingleton1:cn.shentianlan.studytest.designmode.singleton.GeneralSingleton@2a098129--705265961
generalSingleton2:cn.shentianlan.studytest.designmode.singleton.GeneralSingleton@2a098129--705265961
generalSingleton1==generalSingleton2:true