单例模式分为两大种,一种是饿汉模式,一种是懒汉模式(懒加载)
饿汉模式
1.单例-饿汉模式 占用内存常驻,静态常量直接初始化
public class Singleton01 {
//单例-饿汉模式 占用内存常驻
private Singleton01() {
if(SINGLETON!=null){
throw new RuntimeException();
}
}
private static final Singleton01 SINGLETON = new Singleton01();
public Singleton01 getInstance() {
return SINGLETON;
}
}
2.单例-饿汉模式 不占用内存常驻,采用静态内部类直接初始化
public class Singleton02 {
//单例-饿汉模式 不占用内存常驻
private static class Singleton02Inner {
private static final Singleton02 SINGLETON = new Singleton02();
}
private Singleton02() {
if (Singleton02Inner.SINGLETON != null) {
throw new RuntimeException();
}
}
public Singleton02 getInstance() {
return Singleton02Inner.SINGLETON;
}
3.采用枚举类型
public enum Singleton03 {
//枚举实例
SINGLETON;
public void otherMethod() {
}
}
懒汉模式(懒加载)
4.单例-懒汉模式 实现懒加载,线程不安全,多线程时,不一定只有一个实例
public class Singleton04 {
//单例-懒汉模式 实现懒加载,线程不安全
private static Singleton04 singleton = null;
private Singleton04() {
if (singleton != null) {
throw new RuntimeException();
}
}
public static Singleton04 getInstance() {
if (singleton == null) {
singleton = new Singleton04();
}
return singleton;
}
public static void main(String[] args) {
System.out.println(getInstance() == getInstance());
}
}
5.单例-懒汉模式 线程安全写法,但是效率不高,开销大
public class Singleton05 {
//单例-懒汉模式 线程安全写法,但是效率不高,开销大
private static Singleton05 singleton = null;
private Singleton05() {
if (singleton != null) {
throw new RuntimeException();
}
}
public static synchronized Singleton05 getInstance() {
if (singleton == null) {
singleton = new Singleton05();
}
return singleton;
}
public static void main(String[] args) {
System.out.println(getInstance() == getInstance());
}
}
6.单例-懒汉模式 线程不完全安全写法,效率比同步方法高,双重校验锁
public class Singleton06 {
//单例-懒汉模式 线程不完全安全写法,效率比同步方法高,双重校验锁
private static Singleton06 singleton = null;
private Singleton06() {
if (singleton != null) {
throw new RuntimeException();
}
}
public static Singleton06 getInstance() {
if (singleton == null) {
synchronized (Singleton06.class) {
if (singleton == null) {
singleton = new Singleton06();
}
}
}
return singleton;
}
}
7.单例-懒汉模式 线程安全写法,效率比同步方法高,双重校验锁升级版
public class Singleton07 {
//单例-懒汉模式 线程安全写法,效率比同步方法高,双重校验锁升级版
//volatile 起到禁止指令重排的作用,在它赋值完成之前,就不会调用读操作(singleton == null)。
private static volatile Singleton07 singleton = null;
private Singleton07() {
if (singleton != null) {
throw new RuntimeException();
}
}
public static Singleton07 getInstance() {
if (singleton == null) {
synchronized (Singleton07.class) {
if (singleton == null) {
singleton = new Singleton07();
}
}
}
return singleton;
}
}
8.使用 ThreadLocal 实现(线程安全)
public class Singleton08 {
//使用 ThreadLocal 实现(线程安全)
//ThreadLocal 会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。
//对于多线程资源共享的问题,
// 同步机制采用了“以时间换空间”的方式,而ThreadLocal 采用了“以空间换时间”的方式。
// 前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,
// 因此可以同时访问而互不影响。
private static final ThreadLocal<Singleton08> SINGLETON = new ThreadLocal<Singleton08>() {
@Override
protected Singleton08 initialValue() {
return new Singleton08();
}
};
private Singleton08() {
}
public static Singleton08 getInstance() {
return SINGLETON.get();
}
}
9.CAS锁实现,比较再交换(线程安全)
public class Singleton09 {
//CAS锁实现,比较再交换
private static final AtomicReference<Singleton09> SINGLETON = new AtomicReference<>();
private Singleton09() {
}
public static final Singleton09 getInstance() {
for (; ; ) {
Singleton09 current = SINGLETON.get();
if (current != null) {
return current;
}
current = new Singleton09();
if (SINGLETON.compareAndSet(null, current)) {
return current;
}
}
}
public static class MyTest {
@Test
public void test() throws InterruptedException {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
try {
for (int i = 0; i < 100000; i++) {
long i1 = i ^ 5;
System.out.println(i1);
}
System.out.println("aaaa");
notifyAll();
Thread.currentThread().sleep(10000);
System.out.println("fdsafsa");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
th.start();
th.join();
System.out.println("woshitest");
}
}
}