一、推荐使用-饿汉式
/**
* 饿汉式
* 类加载到内存后,就实例化一个单例,JVM保证线程安全
* 简单实用,推荐使用
* 唯一缺点:不管用到与否,类加载时就完成实例化
*/
public class Singleton1 {
private static final Singleton1 INSTANCE = new Singleton1();
private Singleton1(){};
public static Singleton1 getInstance(){
return INSTANCE;
}
public static void main(String[] args) {
Singleton1 s1 = getInstance();
Singleton1 s2 = getInstance();
System.out.println(s1 == s2);
}
}
二、变种饿汉式
public class Singleton2 {
private final static Singleton2 INSTANCE;
static {
INSTANCE = new Singleton2();
}
private Singleton2() {
}
public static Singleton2 getInstance() {
return INSTANCE;
}
}
三、懒汉式
/**
* 懒汉式
* 什么时候用什么时候加载,虽然达到了按需初始化的目的,但却带来线程不安全的问题(多线程访问会出问
* 题)
*/
public class Singleton3 {
private static Singleton3 INSTANCE;
private Singleton3(){};
public static Singleton3 getInstance(){
if (INSTANCE == null){
INSTANCE = new Singleton3();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100; i++){
new Thread(()->{
System.out.println(Singleton3.getInstance().hashCode());
}).start();
}
}
}
四、加锁懒汉式
/**
* 也称懒汉式
* 虽然达到了按需初始化的目的,但在多线程访问下出现问题
* 可以通过synchronized解决,但也带来了效率下降
*/
public class Singleton4 {
private static Singleton4 INSTANCE;
private Singleton4(){};
// 每次调用都加锁,降低效率
public static synchronized Singleton4 getInstance(){
if (INSTANCE == null){
INSTANCE = new Singleton4();
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0;i < 100; i++){
new Thread(()->{
System.out.println(Singleton4.getInstance().hashCode());
}).start();
}
}
}
五、加锁懒汉式2
/**
* 也称懒汉式
* 虽然达到了按需初始化的目的,但在多线程访问下出现问题
* 可以通过synchronized解决,但也带来了效率下降
*/
public class Singleton5 {
private static Singleton5 INSTANCE;
private Singleton5() {
}
;
public static Singleton5 getInstance() {
if (INSTANCE == null) {
//妄图通过减小同步代码的方式提高效率,但不可行,依然在多线程情况下会出现问题
synchronized (Singleton5.class) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
INSTANCE = new Singleton5();
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(Singleton5.getInstance().hashCode());
}).start();
}
}
}
六、加锁懒汉式-号称最完美的写法
/**
* 也称懒汉式
* 虽然达到了按需初始化的目的,但在多线程访问下出现问题
* 可以通过synchronized解决,但也带来了效率下降
*/
public class Singleton6 {
private static volatile Singleton6 INSTANCE;
private Singleton6() {
}
public static Singleton6 getInstance() {
if (INSTANCE == null) {
//双重检查
synchronized (Singleton6.class) {
if (INSTANCE == null) {
try {
Thread.sleep(1);
} catch (Exception e) {
e.printStackTrace();
}
INSTANCE = new Singleton6();
}
}
}
return INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
System.out.println(Singleton6.getInstance().hashCode());
}).start();
}
}
}
七、静态内部类式
/**
* 静态内部类方式
* 加载外部类时不会加载内部类,这样可以实现懒加载
*/
public class Singleton7 {
private Singleton7() {
}
private static class Singleton7Holder {
private static final Singleton7 INSTANCE = new Singleton7();
}
public static Singleton7 getInstance() {
return Singleton7Holder.INSTANCE;
}
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Singleton7.getInstance().hashCode());
}
}
}
八、枚举式-完美中的完美
/**
* 枚举
* 不仅可以解决线程同步,还可以防止反序列化
*/
public enum Singleton8 {
INSTANCE;
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
System.out.println(Singleton8.INSTANCE.hashCode());
}
}
}