单例模式的八种实现方式
package singleton;
public class Singleton01 {
public static void main(String[] args) {
S2 s2 = S2.getS2();
}
}
//饿汉式(静态变量)
class S1{
//构造器必须私有化
private S1(){
}
//方法为静态,故变量也必须为静态,
//访问权限必须为private,假如为public,每次S1.s1,都会new一个新对象
//不符合单例模式
private final static S1 s1 = new S1();
//必须提供静态方法而不是非静态,因为构造器已经私有化,
// 外部不能创建对象,不能调用方法
public static S1 getS1(){
return s1;
}
}
//饿汉式(静态代码块)
class S2{
//私有化构造器
private S2() {}
//
private static S2 s2 ;
static {
s2= new S2();
}
public static S2 getS2(){
return s2;
}}
//懒汉式,线程不安全,
class S3{
//私有化构造器
private S3(){};
//声明成员变量s3,
private static S3 s3;
//调用方法时才创建对象,单线程可用,多线程可能会创建多个对象
public static S3 getS3(){
if(s3 == null){
s3 = new S3();
}
return s3;
}
}
//懒汉式,线程安全,效率太低,不推荐
class S4{
//私有化构造器
private S4(){};
//声明成员变量s4,
private static S4 s4;
//调用方法时才创建对象,效率太低
public static synchronized S4 getS4(){
if(s4 == null){
s4 = new S4();
}
return s4;
}
}
//懒汉式,线程安全,效率太低,不推荐
class S5{
//私有化构造器
private S5(){};
//声明成员变量s4,
private static S5 s5;
//调用方法时才创建对象,效率太低
public static S5 getS5(){
if(s5 == null){
//当第一个线程进来时,new了一个对象,
//第二个线程获得锁的时候,s5不等于null
synchronized (S5.class) {
s5 = new S5();
}
}
return s5;
}
}
//双重检查
class S6{
private S6(){};
private static volatile S6 s6;
public static synchronized S6 getS6(){
if(s6 == null){
synchronized (S6.class){
if(s6 == null){
s6 = new S6();
}
}
}
return s6;
}
}
//静态内部类
class S7{
private S7(){};
//静态成员内部类的private,使外部其他类无法访问该静态内部类
//内部类的属性的private,在外部其他类可以访问该静态内部类
// (即内部的访问修饰符不为private时),使其无法访问内部类的属性
private static class SingletonInstance{
private static final S7 s7 = new S7();
}
//可以访问内部类的私有属性,调用方法时,jvm加载静态内部类,创建S7实例
//只会加载一次,由JVM保证单例和线程安全性
public S7 getS7(){
return SingletonInstance.s7;
}
}
//枚举
enum S8{
INSTANCE;
}



