/*饿汉式单例
它是在类加载的时候就立即初始化,并且创建单例对象
优点:没有加任何的锁、执行效率比较高,
在用户体验上来说,比懒汉式更好
缺点:类加载的时候就初始化,不管你用还是不用,我都占着空间
浪费了内存,有可能占着茅坑不拉屎
绝对线程安全,在线程还没出现以前就是实例化了,不可能存在访问安全问题*/
public class Hungry {
private Hungry() {
}
//先静态、后动态
//先属性、后方法
//先上后下
private static final Hungry hungry = new Hungry();
public static Hungry getInstance() {
return hungry;
}
}
//懒汉式单例一
//在外部需要使用的时候才进行实例化
public class LazyOne {
private LazyOne(){}
//静态块,公共内存区域
private static LazyOne lazy = null;
public static LazyOne getInstance(){
//调用方法之前,先判断
//如果没有初始化,将其进行初始化,并且赋值
//将该实例缓存好
if(lazy == null){
//两个线程都会进入这个if里面
lazy = new LazyOne();
}
//如果已经初始化,直接返回之前已经保存好的结果
return lazy;
}
}
//懒汉式单例二
public class LazyTwo {
private LazyTwo(){}
private static LazyTwo lazy = null;
public static synchronized LazyTwo getInstance(){
if(lazy == null){
lazy = new LazyTwo();
}
return lazy;
}
}
//懒汉式单例三
//特点:在外部类被调用的时候内部类才会被加载
//内部类一定是要在方法调用之前初始化
//巧妙地避免了线程安全问题
//这种形式兼顾饿汉式的内存浪费,也兼顾synchronized性能问题
//完美地屏蔽了这两个缺点
//史上最牛B的单例模式的实现方式
public class LazyThree {
private boolean initialized = false;
//默认使用LazyThree的时候,会先初始化内部类
//如果没使用的话,内部类是不加载的
private LazyThree(){
synchronized (LazyThree.class){
if(initialized == false){
initialized = !initialized;
}else{
throw new RuntimeException("单例已被侵犯");
}
}
}
//每一个关键字都不是多余的
//static 是为了使单例的空间共享
//保证这个方法不会被重写,重载
public static final LazyThree getInstance(){
//在返回结果以前,一定会先加载内部类
return LazyHolder.LAZY;
}
//默认不加载
private static class LazyHolder{
private static final LazyThree LAZY = new LazyThree();
}
}
//双检单利
public class DubbleSingleton {
private static DubbleSingleton ds;
public static DubbleSingleton getDs(){
if(ds == null){
try {
//模拟初始化对象的准备时间...
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (DubbleSingleton.class) {
if(ds == null){
ds = new DubbleSingleton();
}
}
}
return ds;
}
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t2");
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(DubbleSingleton.getDs().hashCode());
}
},"t3");
t1.start();
t2.start();
t3.start();
}
}