第二次梳理:一个类只能产生一个对象,饿汉式是类加载时直接创建对象,懒汉式是第一个获取该对象的时候创建,静态内部类方式是一种最佳实践,即可以实现懒加载、线程安全,还不加锁!有限多利模式是对单例模式的扩展,一个类允许产生有限数量个对象,使用者按照一定规则使用这些对象!时间:2021年05月13日 09点23分40秒
实现方式:饿汉式、懒汉式;
也就是在需要频繁“创建-使用-销毁-在创建……”的情况下(经常用,但是用来用去用的东西都是一样的),使用单例模式提升性能节省资源!时间:2021年05月13日 09时43分17秒
Spring的bean默认就是单例模式,可以理解为单例模式是很常用的,那些功能类(非实体类)只是为了调用方法,而没有任何属性,只需要一个单例就可以完成!时间:2021年05月13日 09时50分37秒
类一旦接在就创建实例,保证在调用‘getInstance()
方法之前单例就已经存在了;
package com.zibo.design.one;
public class Dog {
// 声明的时候直接实例化
private static final Dog instance = new Dog();
private final String name;
private final int age;
// private,防止外部实例化
private Dog() {
this.name = "小黑";
this.age = 1;
System.out.println("Dog被实例化了!");
}
// 返回实例对象
public static Dog getInstance(){
return instance;
}
// Dog自述
public void say(){
System.out.println("我叫" + name + ",我" + age + "岁了!");
}
}
package com.zibo.design.one;
public class Test {
public static void main(String[] args) {
Dog.getInstance().say();
Dog.getInstance().say();
}
}
Dog被实例化了!
我叫小黑,我1岁了!
我叫小黑,我1岁了!
饿汉式单例在类创建的同时就已经创建好一个静态的对象供系统使用,以后不再改变,所以是线程安全的,可以直接用于多线程而不会出现问题;
类加载时没有生成单例,只有当第一次调用 getlnstance()
方法时才去创建这个单例;
package com.zibo.design.one;
public class Dog {
// 使用volatile关键字,保证instance在所有线程中同步(消耗性能)
private static volatile Dog instance = null;
private final String name;
private final int age;
// private,防止外部实例化
private Dog() {
this.name = "小黑";
this.age = 1;
System.out.println("Dog被实例化了!");
}
// 使用synchronized关键字,同步方法执行(消耗性能)
public static synchronized Dog getInstance(){
if(instance == null){
instance = new Dog();
}
return instance;
}
// Dog自述
public void say(){
System.out.println("我叫" + name + ",我" + age + "岁了!");
}
}
package com.zibo.design.one;
public class Dog {
// 使用volatile关键字,保证instance在所有线程中同步(消耗性能)
private static volatile Dog instance = null;
private final String name;
private final int age;
// private,防止外部实例化
private Dog() {
this.name = "小黑";
this.age = 1;
System.out.println("Dog被实例化了!");
}
// 使用synchronized关键字,同步方法执行(消耗性能)
// 这么写能更加节省性能
// 双重验证是必要的
public static Dog getInstance(){
if(instance == null){
synchronized (Dog.class){
if(instance == null){
instance = new Dog();
}
}
}
return instance;
}
// Dog自述
public void say(){
System.out.println("我叫" + name + ",我" + age + "岁了!");
}
}
与饿汉式一致,省略;
访问时需要同步,即使优化后也会消耗额外的性能和资源;
能实现懒加载、是线程安全的,不用锁实现;
package com.zibo.design.one;
public class Dog {
private final String name;
private final int age;
private static class DogHelper{
private static final Dog dog = new Dog();
}
// private,防止外部实例化
private Dog() {
this.name = "小黑";
this.age = 1;
System.out.println("Dog被实例化了!");
}
// 获取实例
public static Dog getInstance(){
return DogHelper.dog;
}
// Dog自述
public void say(){
System.out.println("我叫" + name + ",我" + age + "岁了!");
}
}
与饿汉式一致,省略;
能实现懒加载,线程安全,不需要加锁,简直完美!
是对单例模式的扩展;
生成有限个实例并保存在 ArrayList 中,客户需要时可随机获取;
package com.zibo.design.one;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Dog {
// 存放多个实例的数组
private static final List<Dog> list = new ArrayList<>();
// 实例的最大数量
private static final int INSTANCE_MAX = 3;
private final String name;
private final int age;
// private,防止外部实例化
private Dog(String name, int age) {
this.name = name;
this.age = age;
}
// 使用synchronized关键字,同步方法执行(消耗性能)
// 这么写能更加节省性能
public static Dog getInstance(){
if(list.size() < INSTANCE_MAX){
synchronized (Dog.class){
if(list.size() < INSTANCE_MAX){
// 这里随机设置属性
list.add(new Dog("小黑" + new Random().nextInt(100),new Random().nextInt(10)));
}
}
}
// 随机获取一个
return list.get(new Random().nextInt(list.size()));
}
// Dog自述
public void say(){
System.out.println("我叫" + name + ",我" + age + "岁了!");
}
}
package com.zibo.design.one;
public class Test {
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
new Thread(()-> Dog.getInstance().say()).start();
}
}
}
我叫小黑58,我8岁了!
我叫小黑58,我8岁了!
我叫小黑85,我3岁了!
我叫小黑39,我4岁了!
我叫小黑39,我4岁了!