什么是单例
确保一个系统中只有一个实例
使用场景(为什么使用单例)
有些对象需要频繁new,减少开销
N种写法
私有化构造方法,防止其他地方new,提供获取对象的方法;懒汉式:第一次用到才去创建对象;饿汉式:默认创建对象
1. 简单懒汉式(线程不安全)
/**
* @description 懒汉式,线程不安全
* @date 2020/12/5 10:45
*/
public class SimpleLazySingleton {
//懒汉式
private static SimpleLazySingleton instance;
//私有
private SimpleLazySingleton() {
}
//获取对象的方法
public static SimpleLazySingleton getInstance() {
if(instance == null) {
//测试线程不安全,先sleep 1
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new SimpleLazySingleton();
}
return instance;
}
public static void main(String[] args) {
for(int i = 0; i < 100; i ++) {
new Thread(()->{
System.out.println(SimpleLazySingleton.getInstance().hashCode());
}).start();
}
}
}
2. 简单懒汉式(线程安全)
加锁
/**
* @description 懒汉式,线程安全,线程堵塞
* @date 2020/12/5 11:24
*/
public class SimpleLazySafeSingleton {
//懒汉式
private static SimpleLazySafeSingleton instance;
//私有
private SimpleLazySafeSingleton() {
}
//获取对象的方法 加锁
public static synchronized SimpleLazySafeSingleton getInstance() {
if(instance == null) {
//测试线程安不安全,先sleep 1
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
instance = new SimpleLazySafeSingleton();
}
return instance;
}
public static void main(String[] args) {
for(int i = 0; i < 100; i ++) {
new Thread(()->{
System.out.println(SimpleLazySafeSingleton.getInstance().hashCode());
}).start();
}
}
}
3. 基于第二种优化懒汉式(线程安全)
需要使用volatile的原因
/**
* @description 懒汉式相对优化的单例
* @date 2020/12/5 11:28
*/
public class LazySafeSingleton {
//懒汉式
private static volatile LazySafeSingleton instance;
//私有
private LazySafeSingleton() {
}
//获取对象的方法
public static LazySafeSingleton getInstance() {
//先判断,减少锁
if(instance == null) {
//测试线程安不安全,先sleep 1
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//减少加锁的范围 加锁
synchronized(LazySafeSingleton.class) {
if(instance == null) {
instance = new LazySafeSingleton();
}
}
}
return instance;
}
public static void main(String[] args) {
for(int i = 0; i < 100; i ++) {
new Thread(()->{
System.out.println(LazySafeSingleton.getInstance().hashCode());
}).start();
}
}
}
4. 简单饿汉式单例,线程安全,默认创建了对象
package jiea;
/**
* @description 简单饿汉式单例,线程安全,即使没使用也会创建对象
* @date 2020/12/5 11:33
*/
public class SimpleHungrySingleton {
//创建对象
private static SimpleHungrySingleton instance = new SimpleHungrySingleton();
//私有化构造方法
private SimpleHungrySingleton() {
}
//获取对象的方法
public static SimpleHungrySingleton getInstance() {
return instance;
}
public static void main(String[] args) {
for(int i = 0; i < 100; i ++) {
new Thread(()->{
System.out.println(SimpleHungrySingleton.getInstance().hashCode());
}).start();
}
}
}
5. 基于第4种优化,线程安全由jvm保证
/**
* @author wuwj
* @description 内部类静态变量单例
* @date 2020/12/5 11:42
*/
public class InnerClassLazySafeSingleton {
//私有化
private InnerClassLazySafeSingleton() {
}
private static class InnerClass{
private static InnerClassLazySafeSingleton instance = new InnerClassLazySafeSingleton();
}
//获取对象的方法
public static InnerClassLazySafeSingleton getINstance(){
return InnerClass.instance;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(InnerClassLazySafeSingleton.getINstance().hashCode());
}).start();
}
}
}
6. 枚举实现单例,线程安全,还可以避免反射
package jiea;
/**
* @description 基于枚举实现的单例
* @date 2020/12/5 11:58
*/
public enum EnumSingleton {
INSTANCE;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
System.out.println(EnumSingleton.INSTANCE.hashCode());
}).start();
}
}
}
==========================end==================
菜鸟也想飞的更高