你太不小心了,被我抓住了~
你逃不了了~
文章目录
- JavaEE & 线程案例 & 单例模式 and 阻塞队列
- 1. 设计模式
- 2. 单例模式
- 2.1 单例的含义
- 2.2 初步代码设计
- 2.2.1 饿汉模式
- 2.2.2 懒汉模式
- 2.3 线程安全角度分析
- 2.3.1 对于饿汉模式
- 2.3.2 对于懒汉模式
- 2.4 处理懒汉模式线程不安全问题
- 3. 阻塞队列
- 3.1 阻塞特性
- 3.2 Java标准库内自带的阻塞队列BlockingQueue接口
- 3.2.1 方法1 put入队列
- 3.2.2 方法2 take出队列
- 3.3 阻塞队列的好处
- 3.3.1 生产者消费者模型
- 3.3.2 生产者消费者模型的优点
- 3.4 代码实现生产者消费者模型
- 3.4.1 生产者 < 消费者
- 3.4.2 生产者 > 消费者
- 3.4.3 正常写法
- 3.5 模拟实现阻塞队列
- 3.5.1 属性
- 3.5.2 构造方法
- 3.5.3 put方法
- 3.5.4 take方法
- 3.5.5 循环队列原理小小复习
- 3.5.6 修复小瑕疵
- 3.5.7 测试
下棋有棋谱
弹奏有乐谱
而计算机设计模式,是前人总结下来的一些代码编写套路
主要是因为大佬的代码和其他人的代码能力差距实在是大
设计模式有很多种(不是23种~)
之前有个大佬写了本书,讨论了23种设计模式
(1条消息) 设计模式23模式介绍_哪 吒的博客-CSDN博客
在现阶段,主要要掌握的有两种:
单例 ==> single instance ==> 单个实例对象
就有一些场合,限制一个类只能有一个对象,而不是多个对象去分担资源。
这些限制是符合“初心写代码”,“针对性写代码”的~
而单例模式有多种写法:
就比如说,你打开一个1000页的pdf
没错
class Singleton {
private static Singleton instance = new Singleton();
public static Singleton getInstance() {
return instance;
}
private Singleton() {
}
}
public class Test {
public static void main(String[] args) {
Singleton s1 = Singleton.getInstance();
//Singleton s2 = new Singleton();报错~
}
}
那么instance就仅此一份了~
一方面保证单例的特性----“初心” + “针对性”
class SingletonLazy {
private static SingletonLazy singletonLazy = null;
public static SingletonLazy getSingletonLazy() {
if(singletonLazy == null) {
singletonLazy = new SingletonLazy();
}
return singletonLazy;
}
private SingletonLazy() {
}
}
public class Test {
public static void main(String[] args) {
SingletonLazy s1 = SingletonLazy.getSingletonLazy();
SingletonLazy s2 = SingletonLazy.getSingletonLazy();
System.out.println(s1 == s2);
}
}
对于懒汉模式而言,单例第一次实例是在第一次get的时候
而这里就会出现一个很重要的问题!
回忆一波,这个场景很熟悉~
在这里插入图片描述
如图,这个操作可以分为这两步~
那就有以下这种极端情况~
首先,先提一下单例模式的重要性
这两个方法是阻塞队列的核心方法,其他方法跟普通队列别无二致~
peek的时候队列空,阻塞等待,但是几乎不用这个方法和其他方法~
写多线程代码时,多线程之间若进行数据交互,可以用阻塞队列简化代码编写~
在go语言中,支持多并发编程,并且引入了一个“轻量级线程”的“协程”,协程与协程之间进行交互数据的时候,会通过一个阻塞队列:channel
举个栗子:
由于阻塞队列非常好使,大佬们将阻塞队列功能单独拎出来做成一个单独的服务器~
下面将介绍一些情景~
大部分是线程不安全的~
当这只是打印顺序问题~
但是阻塞队列绝对是安全的
还有“死锁”情况
public class Test1 {
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(5);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(100);
blockingQueue.put(1);
System.out.println("生产1个");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(10);
blockingQueue.take();
System.out.println("消耗1个");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
}
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(10);
synchronized (blockingQueue) {
blockingQueue.take();
System.out.println("消耗1个");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
改动两个线程:
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(5);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(100);
synchronized (blockingQueue) {
blockingQueue.put(1);
System.out.println("生产1个");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(10);
synchronized (blockingQueue) {
blockingQueue.take();
System.out.println("消耗1个");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(5);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(10);
blockingQueue.put(1);
System.out.println("生产1个");}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(100);
blockingQueue.take();
System.out.println("消耗1个");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(5);
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(10);
blockingQueue.put(1);
System.out.println("生产1个");}
catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
Thread.sleep(100);
synchronized (blockingQueue) {
blockingQueue.take();
System.out.println("消耗1个");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
一般不会让两个线程都不sleep
让一方留足够的时间等对方~
public static void main(String[] args) {
BlockingQueue<Integer> blockingQueue = new LinkedBlockingQueue<>(5);
Object o = new Object();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
System.out.println("生产1个");
blockingQueue.put(1);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t1.start();
Thread t2 = new Thread(() -> {
for (int i = 0; i < 25; i++) {
try {
blockingQueue.take();
System.out.println("消耗1个");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
t2.start();
}
这样,线程1只要put1个,线程2就会立马take掉~
测试:
这里的循环队列跟之前数据结构讲的循环队列,整体结构是一样的
两种方式确定队列是满是空:
用什么底层数据结构
在适当的时机,设计wait和notify的对应代码
public class MyBlockingQueue {
volatile private int[] items;
volatile private int front;
volatile private int rear;
private final static int INIT = 10;
private int size;
public MyBlockingQueue(int capacity) {
this.items = new int[capacity];
}
synchronized public void put(int value) throws InterruptedException {
if(size == items.length) {
this.wait();
}
items[rear] = value;
rear = (rear + 1) % items.length;
size++;
this.notify();
}
synchronized public int take() throws InterruptedException {
if(size == 0) {
this.wait();
}
int ret = items[front];
front = (front + 1) % items.length;
size--;
this.notify();
return ret;//ret刚刚跳出队列的元素~
}
public MyBlockingQueue() {
this.items = new int[INIT];
}
}
volatile private int[] items;
volatile private int front;
volatile private int rear;
private final static int INIT = 10;
private int size;
public MyBlockingQueue(int capacity) {
if(capacity <= 0) {
//没有容量为0或者小于0的队列~
this.items = new int[INIT];
}
this.items = new int[capacity];
}
public MyBlockingQueue() {
this.items = new int[INIT];
}
synchronized public void put(int value) throws InterruptedException {
if(size == items.length) {
this.wait();
}
items[rear] = value;
rear = (rear + 1) % items.length;
size++;
this.notify();
}
synchronized public int take() throws InterruptedException {
if(size == 0) {
this.wait();
}
int ret = items[front];
front = (front + 1) % items.length;
size--;
this.notify();
return ret;
}
synchronized public int take() throws InterruptedException {
while(size == 0) {
this.wait();
}
int ret = items[front];
front = (front + 1) % items.length;
size--;
this.notify();
return ret;
}
synchronized public void put(int value) throws InterruptedException {
while(size == items.length) {
this.wait();
}
items[rear] = value;
rear = (rear + 1) % items.length;
size++;
this.notify();
}
文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭!