package com.zqh.singleton;
public class SingletonImpl {
public static void main(String[] args) throws Exception {
/**
* 单例设计的核心本质在于:
* 类内部的构造方法私有化,在类的内部产生实例化对象之后通过static方法获取实例化对象进行类中的结构调用。
* 单例设计模式有两类:懒汉式、饿汉式。这次主要讨论懒汉式。
*/
// Singleton1 singleton = Singleton1.getInstance();
// singleton.print();
/**
* 以上为单线程,下面使用多线程看看
*/
for (int i = 0; i < 3; i++) {
new Thread(()->{
Singleton2.getInstance().print();
},"Thread-"+i).start();
/**
* Lambda,JDK1.8
*/
// new Thread(new Runnable() {
// @Override
// public void run() {
// Singleton.getInstance().print();
// }
// }).start();
}
}
}
/**
* 饿汉式
*/
class Singleton1{
private static final Singleton1 INSTANCE = new Singleton1();
private Singleton1(){
System.out.println(Thread.currentThread().getName()+"\tSingleton");
}
public static Singleton1 getInstance(){return INSTANCE;}
public void print(){
System.out.println("hi! Singleton!");
}
}
/**
* 运行结果:
* Thread-0 Singleton
* hi! Singleton!
* hi! Singleton!
* hi! Singleton!
* 饿汉式,空间换时间
*/
/**
* 懒汉式
* static、private版
*/
class Singleton2{
private static Singleton2 instance = null;
private Singleton2(){
System.out.println(Thread.currentThread().getName()+"\tSingleton");
}
public static Singleton2 getInstance(){
if(instance == null){
instance = new Singleton2();
}
return instance;
}
public void print(){
System.out.println("hi! Singleton!");
}
}
/**
* 1.运行结果:
* Thread-2 Singleton
* Thread-0 Singleton
* hi! Singleton!
* Thread-1 Singleton
* hi! Singleton!
* hi! Singleton!
* 而单例设计的最大特点是在整体的运行过程之中只允许产生一个实例化对象
* 问题造成的关键在于代码本身出现了不同步的情况,需要进行同步处理,synchronized关键字
*/
/**
* 懒汉式
* getInstance方法体上加synchronized
*/
class Singleton3{
private static Singleton3 instance = null;
private Singleton3(){
System.out.println(Thread.currentThread().getName()+"\tSingleton");
}
public static synchronized Singleton3 getInstance(){
if(instance == null){
instance = new Singleton3();
}
return instance;
}
public void print(){
System.out.println("hi! Singleton!");
}
}
/**
* 2.运行结果:
* Thread-0 Singleton
* hi! Singleton!
* hi! Singleton!
* hi! Singleton!
* 这样同步的代价就是效率会低。
* 因为整体代码里面实际上只有一部分需要进行同步,就是instance对象的实例化处理部分
*/
/**
* 懒汉式
* 实例化部分加synchronized
*/
class Singleton4{
private static Singleton4 instance = null;
private Singleton4(){
System.out.println(Thread.currentThread().getName()+"\tSingleton");
}
public static Singleton4 getInstance(){
if(instance == null){
synchronized(Singleton4.class){
instance = new Singleton4();
}
}
return instance;
}
public void print(){
System.out.println("hi! Singleton!");
}
}
/**
* 3.运行结果:
* Thread-0 Singleton
* hi! Singleton!
* Thread-2 Singleton
* hi! Singleton!
* Thread-1 Singleton
* hi! Singleton!
* 还是不行,因为会有多个线程通过第一个判断
*/
/**
* 懒汉式 完整版
* 双重检查加锁
* static、private、synchronized、volatile
*/
class Singleton{
private static volatile Singleton instance = null;
private Singleton(){
System.out.println(Thread.currentThread().getName()+"\tSingleton");
}
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
if(instance == null){
instance = new Singleton();
}
}
}
return instance;
}
public void print(){
System.out.println("hi! Singleton!");
}
}
/**
* 4.运行结果:
* Thread-0 Singleton
* hi! Singleton!
* hi! Singleton!
* hi! Singleton!
* 对象被实例化的时候,应该立刻与主内存中的数据对象进行同步,而不应该存副本。
* 所以最好在加个volatile关键字 (可见性)
*/
/**
* 面试题:请编写单例设计模式
* 1.直接编写一个饿汉式的单例设计模式,并且实现构造方法私有化;
* 2.在Java中哪里使用到单例设计模式了?Runtime类、Spring框架;
* 3.懒汉式单例设计模式的问题?
*/