目录
一、单例模式
1,什么是单例模式
设计模式好比象棋中的 "棋谱". 红方当头炮, 黑方马来跳. 针对红方的一些走法, 黑方应招的时候有 一些固定的套路. 按照套路来走局势就不会吃亏
软件开发中也有很多常见的 "问题场景". 针对这些问题场景, 大佬们总结出了一些固定的套路. 按照 这个套路来实现代码, 也不会吃亏
2,单例模式分类
饿汉模式
类加载的同时, 创建实例.
//先创建一个表示单例的类
//我们要求Singletion这个类只能有一个实例
//饿汉模式,“饿”是指类被加载,实例就会被创建
static class Singletion{
//把构造方法变为私有,此时该类外部就无法new这个类的实例
private Singletion(){}
//创建一个static的成员,表示该类的唯一实例
private static Singletion instance = new Singletion();
public static Singletion getInstance() {
return instance;
}
}
public static void main(String[] args) {
Singletion s1 = Singletion.getInstance();
Singletion s2 = Singletion.getInstance();
System.out.println(s1 == s2);
}
懒汉模式
单线程
class Singleton {
private static Singleton instance = null;
private Singleton() {}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
但以上代码存在线程不安全的问题
对于懒汉模式,多线程调用getInstance,getInstance做了四件事
读取instance的内容
判断instance是否为空
如果instance为null,就new实例
返回实例地址
当一个类被new两次,就不是单例模式了,如果线程更多,new的次数可能更多,不符合单例模式
多线程
static class Singletion{
private Singletion() { }
private static Singletion instance = null;
public static Singletion getInstance(){
if (instance == null){
instance = new Singletion();
}
return instance;
}
}
保证线程安全,我们选择加锁
static class Singletion{
private Singletion() { }
private static Singletion instance = null;
public static Singletion getInstance(){
synchronized (Singletion.class){
if (instance == null){
instance = new Singletion();
}
return instance;
}
}
}
当多线程首次调用 getInstance, 大家可能都发现 instance 为 null, 于是又继续往下执行来竞争锁, 其中竞争成功的线程, 再完成创建实例的操作
当这个实例创建完了之后, 其他竞争到锁的线程就被里层 if 挡住了. 也就不会继续创建其他实例
static class Singletion{
private Singletion() { }
private static Singletion instance = null;
public static Singletion getInstance(){
if (instance == null){
synchronized (Singletion.class){
if (instance == null){
instance = new Singletion();
}
}
}
return instance;
}
}
}
涉及多个读操作,可能会被编译器优化,为了避免 "内存可见性" 导致读取的 instance 出现偏差, 于是补充上 volatile。
static class Singletion{
private Singletion() { }
private volatile static Singletion instance = null;
public static Singletion getInstance(){
if (instance == null){
synchronized (Singletion.class){
if (instance == null){
instance = new Singletion();
}
}
}
return instance;
}
}
为了保证线程安全,涉及三个要点
1,加锁保证线程安全
2,双重if保证效率
3,volatile避免了内存可见性的问题
二,生产者消费者模型
1,阻塞队列是什么
阻塞队列是一种特殊的队列. 也遵守 "先进先出" 的原则. 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性:
当队列满的时候, 继续入队列就会阻塞, 直到有其他线