(一)饿汉式(静态常量)
public class Test1 {
/**
* 饿汉式(静态常量)
* 优点:简单好设计,同时避免了多线程同步的问题,在类加载的时候就初始化了
* 缺点:在类加载就初始化好了这个实例,没有达到lazy load的效果,如果程序在一直没有使用过这个实例,
* 那么就会造成内存的浪费。
*/
//首先是构造器私有化,在类外部就不能new
private Test1(){}
//在类加载的时候就初始化类,避免了线程同步问题
public static final Test1 test1=new Test1();
//在类外部获取Test1对象
public static Test1 getInstance(){
return test1;
}
}
(二)饿汉式(静态代码块实现)
public class Test2 {
/**
* 饿汉式(静态代码块实现)
* 优点:简单好设计,同时避免了多线程同步的问题,在类加载的时候就初始化了
* 缺点:在类加载就初始化好了这个实例,没有达到lazy load的效果,如果程序在一直没有使用过这个实例,
* 那么就会造成内存的浪费。
*/
//首先是构造器私有化,在类外部就不能new
private Test2(){}
//在类加载的时候就初始化类,避免了线程同步问题
public static Test2 test2;
//也是在类加载就初始化
static {
test2=new Test2();
}
//在类外部获取Test1对象
public static Test2 getInstance(){
return test2;
}
}
(三) 懒汉式(线程不安全)
public class Test3 {
/**
* 懒汉式(线程不安全)
* 优点:达到了lazy load加载的效果,没有人使用也不会浪费内存
* 缺点:出现了线程不安全问题,比如在if()判断的时候刚好由多个线程进来了,
* 此时就会new出多个对象,造成线程不安全的问题
*/
//定义静态属性
private static Test3 test3;
//构造器私有化
private Test3(){};
//获取实例
public static Test3 getInstance(){
if (test3==null){
return new Test3();
}
return test3;
}
}
(四)懒汉式(线程安全,同步方法)
public class Test4 {
/**
* 懒汉式(线程安全,同步方法)
* 优点:达到了lazy load加载的效果,没有人使用也不会浪费内存,解决了线程不安全问题
* 缺点:效率太低了,因为在静态方法上加入了synchronized同步代码块,
* 也就是当我们在调用该方法的时候,都需要排队调用。
*/
//定义静态属性
private static Test4 test4;
//构造器私有化
private Test4(){};
//获取实例
public static synchronized Test4 getInstance(){
if (test4==null){
test4=new Test4();
}
return test4;
}
}
(五) 双重检查
public class Test5 {
/**
* 双重检查
* 优点:提高了效率,也解决了线程同步问题,也达到了lazy load的效果
* 缺点:
*
* volatile:
* 当写一个volatile变量时,JMM会把该线程对应的本地内存中的共享变量值立即刷新回主内存中。
* 当读一个volatile变量时,JMM会把该线程对应的本地内存设置为无效,重新回到主内存中读取最新共享变量。
*/
//定义静态变量
private static volatile Test5 test5;
//构造器私有化
private Test5(){}
//初始化静态属性
public static Test5 getInstance(){
if (test5==null){
synchronized (Test5.class){
if (test5==null){
test5=new Test5();
}
}
}
return test5;
}
}
(六)静态内部类
public class Test6 {
/**
* 静态内部类
* 优点:线程安全,而且满足lazy load效果,
*
*/
private Test6(){}
//静态内部类,类加载之后不会加载初始化
private static class TestInstance {
private static final Test6 test6=new Test6();
}
//调用静态内部类
public static Test6 getInstance(){
return TestInstance.test6;
}
}
(七)枚举单例
public enum Test8 {
INSTANCE;
public void nam(){
System.out.println("sdhsbdhsdhs");
}
}