普通创建对象
/**
* @author jason jason@aistrong.com
* @date 2021/1/21 18:20
*/
/**
* @author jason jason@aistrong.com
* @date 2021/1/21 18:20
*/
public class Person {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
Person person = new Person();
System.out.println(person);
}).start();
}
}
}
输出结果
发现每次创建对象都是新的对象,单例模式要求每次创建的对象是同一个对象
com.aistrong.singleton.Person@74b47802
com.aistrong.singleton.Person@74f84cf
com.aistrong.singleton.Person@72d6db17
com.aistrong.singleton.Person@5015b31e
饿汉式
/**
* 饿汉式
* 优点:写法简单,线程安全
* 缺点:当类被加载到内存中的时候,就会创建对象,造成内存浪费
*
* @author jason jason@aistrong.com
* @date 2020/12/29 0:41
*/
public class Singleton1 {
//私有化构造器
private Singleton1() {
}
//当类被加载的时候就会初始化对象
private static Singleton1 singleton1 = new Singleton1();
//对外提供访问的方法
public static Singleton1 getSingleton1() {
return singleton1;
}
//开启100个线程来获取单例对象,看是否每次获取的是同一个对象
//如果对象的hashCode一致,则证明为同一个对象
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
Singleton singleton = Singleton.getSingleton();
System.out.println(singleton);
}).start();
}
}
}
懒汉式
/**
* 懒汉式
* 优点:不会在类加载到内存中时候就创建对象,相对于饿汉式来说,不会造成内存浪费
* 缺点:因为是第一次使用的时候去创建对象,在多线程环境中容易造成线程不安全问题
* @author jason jason@aistrong.com
* @since 2020/12/29 9:21
*/
public class Singleton {
//1.私有化构造器
private Singleton() {
}
//定义这个单例对象
private static volatile Singleton singleton;
//对外提供方法
//双重检查锁
public static Singleton getSingleton() {
if (singleton == null) {
//对当前类对象加锁。此处如果用lock也能实现
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
//开启100个线程来获取单例对象,看是否每次获取的是同一个对象
//如果对象的hashCode一致,则证明为同一个对象
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
Singleton singleton = Singleton.getSingleton();
System.out.println(singleton);
}).start();
}
}
}
静态内部类式
/**
* 匿名内部类方式
* 优点:即实现了懒加载,又能在不加锁的同时保证线程安全
* 缺点:代码写法比较少见,不能算缺点
* 原理:加载一个类时,其内部类不会同时被加载,一个类被加载时,
* 当且仅当某个静态成员(静态域、构造器、静态方法)被调用时发生
*
* @author jason jason@aistrong.com
* @date 2021/1/21 18:42
*/
public class Singleton2 {
//私有化构造器
private Singleton2() {
}
//静态内部类被调用的时候,创建外部类的实例对象
private static class SonSingleton2 {
private static final Singleton2 instance = new Singleton2();
}
//对外提供静态方法提供实例
public static Singleton2 getInstance() {
return SonSingleton2.instance;
}
//开启100个线程来获取单例对象,看是否每次获取的是同一个对象
//如果对象的hashCode一致,则证明为同一个对象
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(()->{
Singleton2 singleton = Singleton2.getInstance();
System.out.println(singleton);
}).start();
}
}
}
枚举类式
/**
* 枚举类实现单例模式
* 优点:能防止反序列化来创建对象,线程安全
* 缺点:无
*
* @author jason jason@aistrong.com
* @date 2021/1/21 20:27
*/
public enum DataSourceEnum {
DATASOURCE;
private DBConnection connection = null;
//私有化构造器
private DataSourceEnum() {
//内部完成对象创建
connection = new DBConnection();
}
//对外提供实例方法
public DBConnection getConnection() {
return connection;
}
//测试方法
//输出结果发现均为同一个对象
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
new Thread(() -> {
DBConnection connection = DataSourceEnum.DATASOURCE.getConnection();
System.out.println(connection);
}).start();
}
}
}
/**
* 上个类中的 DBConnection
* @author jason jason@aistrong.com
* @date 2021/1/21 20:29
*/
public class DBConnection {
}