单例模式的创建方式众多,这里列出4种创建方式,分别是懒汉式、饿汉式、静态内部类和枚举类单例。
下面的demo代码中都模拟了5个线程同时获取单例实例的场景,模拟使用了CountDownLatch来实现。
懒汉式单例创建
/**
* 懒汉式单例
*/
public class Singleton1 {
private static Singleton1 singleton1;
private Singleton1(String name) {
System.out.println("构造器 Thread Name:" + name);
}
public static Singleton1 getInstance(String name) {
System.out.println("getInstance Thread Name:" + name);
if(singleton1 == null) {
System.out.println("check1 getInstance Thread Name:" + name);
synchronized (Singleton1.class) {
System.out.println("check2 getInstance Thread Name:" + name);
if(singleton1 == null) {
singleton1 = new Singleton1(name);
}
}
}
return singleton1;
}
}
测试
import java.util.concurrent.CountDownLatch;
public class Singleton1Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c = new CountDownLatch(1);
CountDownLatch cdl = new CountDownLatch(5);
for(int i=0; i<5; i++) {
new Thread(()->{
try {
c.await();
Singleton1 instance = Singleton1.getInstance(Thread.currentThread().getName());
System.out.println(instance);
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Thread.sleep(3000);
c.countDown();
cdl.await();
}
}
输出:
getInstance Thread Name:Thread-0
check1 getInstance Thread Name:Thread-0
check2 getInstance Thread Name:Thread-0
getInstance Thread Name:Thread-4
check1 getInstance Thread Name:Thread-4
getInstance Thread Name:Thread-2
check1 getInstance Thread Name:Thread-2
getInstance Thread Name:Thread-1
check1 getInstance Thread Name:Thread-1
getInstance Thread Name:Thread-3
check1 getInstance Thread Name:Thread-3
构造器 Thread Name:Thread-0
check2 getInstance Thread Name:Thread-3
check2 getInstance Thread Name:Thread-1
check2 getInstance Thread Name:Thread-2
com.my.study.design.test.Singleton1@451ae77f
com.my.study.design.test.Singleton1@451ae77f
com.my.study.design.test.Singleton1@451ae77f
check2 getInstance Thread Name:Thread-4
com.my.study.design.test.Singleton1@451ae77f
com.my.study.design.test.Singleton1@451ae77f
饿汉式
/**
* 饿汉式单例
*/
public class Singleton2 {
private static Singleton2 singleton1 = new Singleton2();
private Singleton2() {
System.out.println("构造器 初始化");
}
public static Singleton2 getInstance(String name) {
System.out.println("getInstance Thread Name:" + name);
return singleton1;
}
}
测试
import java.util.concurrent.CountDownLatch;
public class Singleton2Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c = new CountDownLatch(1);
CountDownLatch cdl = new CountDownLatch(5);
for(int i=0; i<5; i++) {
new Thread(()->{
try {
c.await();
Singleton2 instance = Singleton2.getInstance(Thread.currentThread().getName());
System.out.println(instance);
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Thread.sleep(3000);
c.countDown();
cdl.await();
}
}
输出:
构造器 初始化
getInstance Thread Name:Thread-1
getInstance Thread Name:Thread-2
getInstance Thread Name:Thread-3
com.my.study.design.test.Singleton2@451ae77f
getInstance Thread Name:Thread-4
com.my.study.design.test.Singleton2@451ae77f
getInstance Thread Name:Thread-0
com.my.study.design.test.Singleton2@451ae77f
com.my.study.design.test.Singleton2@451ae77f
com.my.study.design.test.Singleton2@451ae77f
静态内部类创建单例
/**
* 静态内部类单例
*/
public class Singleton3 {
private Singleton3() {
System.out.println("Singleton3 new Success");
}
private static class Singleton3Inner {
private static final Singleton3 singleton3 = new Singleton3();
}
public static Singleton3 getInstance(String name) {
System.out.println("getInstance Thread Name:" + name );
return Singleton3Inner.singleton3;
}
}
测试
import java.util.concurrent.CountDownLatch;
public class Singleton3Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c = new CountDownLatch(1);
CountDownLatch cdl = new CountDownLatch(5);
for(int i=0; i<5; i++) {
new Thread(()->{
try {
c.await();
Singleton3 instance = Singleton3.getInstance(Thread.currentThread().getName());
System.out.println(instance);
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Thread.sleep(3000);
c.countDown();
cdl.await();
}
}
输出:
getInstance Thread Name:Thread-0
getInstance Thread Name:Thread-3
Singleton3 new Success
com.my.study.design.test.Singleton3@4b79d4e1
com.my.study.design.test.Singleton3@4b79d4e1
getInstance Thread Name:Thread-2
com.my.study.design.test.Singleton3@4b79d4e1
getInstance Thread Name:Thread-4
com.my.study.design.test.Singleton3@4b79d4e1
getInstance Thread Name:Thread-1
com.my.study.design.test.Singleton3@4b79d4e1
枚举单例:
public enum Singleton4 {
instance;
public void test(String name) {
System.out.println("getInstance Thread Name:" + name );
}
}
测试
import java.util.concurrent.CountDownLatch;
public class Singleton4Test {
public static void main(String[] args) throws InterruptedException {
CountDownLatch c = new CountDownLatch(1);
CountDownLatch cdl = new CountDownLatch(5);
for(int i=0; i<5; i++) {
new Thread(()->{
try {
c.await();
Singleton4.instance.test(Thread.currentThread().getName());
cdl.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
Thread.sleep(3000);
c.countDown();
cdl.await();
}
}
输出:
getInstance Thread Name:Thread-0
getInstance Thread Name:Thread-4
getInstance Thread Name:Thread-2
getInstance Thread Name:Thread-3
getInstance Thread Name:Thread-1