饿汉式:类初始化是不管你需不需要直接创建对象,不存在线程安全问题
直接创建Singleton.java
public class Singleton {
public final static Singleton INSTANCE = new Singleton();
/**
* 构造器私有
*/
private Singleton(){
}
}
枚举Singleton.java
/**
* 枚举式
* 该类型对象是有限的几个,可以限定为一个,那么就是单例了。
*/
public enum Singleton2 {
INSTANCE
}
静态代码块Singleton.java
/**
* 静态代码块
*/
public class Singleton3 {
public final static Singleton3 INSTANCE;
static{
INSTANCE = new Singleton3();
}
private Singleton3(){
}
}
懒汉式:延迟创建实例对象;存在线程安全问题。
线程不安全:Singleton4.java
public class Singleton4 {
//设置成private,怕类一调用:如果没创建对象,则是空的。
private static Singleton4 instance;
//构造器私有话
private Singleton4(){}
public static Singleton4 getInstance() throws InterruptedException {
//判断是否创建,没创建直接创建,创建后直接返回
if(instance==null){
Thread.sleep(2000);
instance = new Singleton4();
}
return instance;
}
}
线程安全:Singleton5.java
适用于多线程
在Singleton4.java
的基础上修改
public static Singleton5 getInstance() throws InterruptedException {
synchronized (Singleton5.class){
//判断是否创建,没创建直接创建,创建后直接返回
if(instance==null){
Thread.sleep(2000);
instance = new Singleton5();
}
}
return instance;
}
以上并不是最优的,以上在第一个线程完成创建之后instance已经部位空。第二个线程可以直接获得,并不用再获得锁。
所以优化后的为
public class Singleton5 {
//设置成private,怕类一调用:如果没创建对象,则是空的。
private static Singleton5 instance;
//构造器私有话
private Singleton5(){}
public static Singleton5 getInstance() throws InterruptedException {
if(instance==null){
synchronized (Singleton5.class){
//判断是否创建,没创建直接创建,创建后直接返回
if(instance==null){
Thread.sleep(2000);
instance = new Singleton5();
}
}
}
return instance;
}
}
以上两个的测试方式:
public class TestSingleton {
public static void main(String[] args) throws ExecutionException, InterruptedException {
/*Singleton4 singleton4 = Singleton4.getInstance();
System.out.println(singleton4);*/
Callable<Singleton4> callable = new Callable<Singleton4>() {
@Override
public Singleton4 call() throws Exception {
return Singleton4.getInstance();
}
};
ExecutorService es = Executors.newFixedThreadPool(2);
Future<Singleton4> submit1 = es.submit(callable);
Future<Singleton4> submit2 = es.submit(callable);
Singleton4 s1 = submit1.get();
Singleton4 s2 = submit2.get();
System.out.println(s1==s2);
System.out.println(s1);
System.out.println(s2);
es.shutdown();
}
}
静态内部类(适用于多线程)Singleton6 .java
/**
* 在内部类被加载和初始化时创建对象
*/
public class Singleton6 {
private Singleton6(){}
private static class inner{
private static Singleton6 instance = new Singleton6();
}
public Singleton6 getSingleton(){
return inner.instance;
}
}
总结:
饿汉式:枚举类最简单
懒汉式:静态内部类形式最简单