队列
今天要给大家带来的是一期关于数据结构上的内容,队列;这里给大家模拟一个现实场景,昨天不是刚刚过2.14嘛,男同胞们会在奶茶店叫奶茶哦,2.14这天恰好人比较多,需要一个一个排队进行等候,在这里结合多线程给大家具体实现一个模型。
首先给大家实现一个循环队列的模型
大家需要具体从队列上了解,请上力扣队列 & 栈图文学 - LeetBook - 力扣(LeetCode)全球极客挚爱的技术成长平台
package Test.Date_23_2_12;
/**
* @ClassName ArrayQueue
* @Description TODO
* @Author Pzy
* @Date 2023/2/12 11:33
* @Version 1.0
**/
public class ArrayQueue {
private int Front,Rear;//头尾指针
private int maxSize;//最大容量
private int QueueArr [];//给定一个存储数组
private int Size;//容量
//构造器
public ArrayQueue(int k)
{
//创建存储数组
this.maxSize = k;//把参数值传给当前对象的最大容量
QueueArr = new int [maxSize];//创建容量为k的数组
Front = -1;//初始化循环队列 头尾指针指向-1
Rear = -1;
Size = 0;//容量为0
}
//入列
public boolean enQueue(int value){
/*
判断队列是否已满
1、满了返回false
2、未满
1.判断队列是否已满,已满则返回false
2.由于是循环队列头指针head需要知道具体位置(不一定在第一个元素的位置)
所以需要判断head 是否 == -1 ,等于-1表示在最初的位置上(未改变)
3.判断尾指针的位置是否在最后的位置(循环队列需要进行头尾指针的判断)
尾指针在最后这说明,指向了第一个元素之前的位置
尾指针 Rear+1 容量 Size+1
*/
if(this.isFull()){
return false;
}
if(this.Front == -1){this.Front = 0;}//说明在原来的位置上
if(this.Rear == maxSize -1) {this.Rear =0;}//队列快满了
else this.Rear++;//尾指针+1
//一般插入情况
this.Size++;//容量+1
this.QueueArr[this.Rear] = value;//数据加入到数组当中
return true;
}
//出列
public boolean deQueue(){
if(this.isEmpty()) return false;//判断是否为null
if (this.Front == maxSize -1) this.Front =0;//判断头指针是否在最初的位置上
else this.Front++;//头指针+1
this.Size--;//出列容量减少
return true;
}
//获取队首元素
//判断队列是否为null
public boolean isFull(){
return this.Size == 0;
}
//判断队列是否已满
public boolean isEmpty() {
return this.Size == maxSize;
}
}
力扣队列代码
/**
* @ClassName Queue
* @Description TODO
* @Author Love yue yue
* @Date 2023/2/14 10:44
* @Version 1.0
**/
public class Queue {
//队列
private int [] data;
private int head;//头指针
private int tail;//尾指针
private int size;//数组大小/容量
//构造器
public Queue(int k) {
data = new int [k];//把参数中的值传入到int 数组需要给定的值当中
head = -1;//头指针初始值
tail = -1;//尾指针初始值
size = k;//k值赋值给数组的容量值
}
//入列 队列尾部进入
public boolean enQueue(int value){
if(isFull() == true){
return false;//如果数组已满 直接返回false
}
if(isEmpty() == true){
head = 0;//如果数组位空,标记头指针的位置
}
tail = (tail+1)%size;
/**
*
*/
data[tail]= value;//入列数据存储到尾指针指向的位置上 尾插法
return true;
}
//出列 队列头部出列
public boolean deQueue(){
//判断队列是否位空 为空则返回false
if(isEmpty() == true){
return false;
}
//头指针和尾指针的值相同的话,说明队列已经空了
if(head == tail){
head = -1;//头指针初始值
tail = -1;//尾指针初始值
return true;
}
//不满足以上情况说明队列没有满
head = (head +1)%size;
return true;
}
//从队列中获取第一项的值
public int Front(){
//判断是否为空,为空则返回false
if(isEmpty() == true){
return -1;//注意此处的返回值时int类型
}
//不为空则进行值的获取
return data[head];
}
//从队列中获取最后第一项的值(和Front相似)
public int Rear(){
//判断是否为空,为空则返回false
if(isEmpty() == true){
return -1;
}
return data[tail];
}
//判断队列是否已满
private boolean isFull() {
//队列已满 ---- >
return ((tail+1)%size) == head;
/**
* 当head == 0 tail = size-1 的时候 或者
* head = tail +1
* 这是队列是否已满的情况两情况(其实是一种)
*/
}
//判断队列是否已空
private boolean isEmpty() {
//队列为空 --->
return head == -1;
}
}
具体要实现一下功能(仿力扣写的功能目标)
- MyCircularQueue(k): 构造器,设置队列长度为 k 。
- Front: 从队首获取元素。如果队列为空,返回 -1 。
- Rear: 获取队尾元素。如果队列为空,返回 -1 。
- enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
- deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
- isEmpty(): 判断循环队列是否为空。
- isFull():判断循环队列是否已满。
下面给大家写了一个使用循环队列和多线程的小Dome (生产者和消费者模型 — 不完整)
需求:有A B C 四个线程 采用流水线方式,A 处理完产品交给B,B处理完产品交给C,C处理完产品交给D
D处理完产品,结束任务。
需要处理的任务:
A处理时 num值增加20
num =num +20
B处理时当前num值乘10
num = num * 10
C处理时当前num值和当前num值相乘
num = num * num
/**
* @ClassName Task
* @Description TODO
* @Author Love yue yue
* @Date 2023/2/13 11:13
* @Version 1.0
**/
public class Task {
int num;
public void taskA(){
num += 20;
}
public void taskB(){
num *= 10;
}
public void taskC(){
num *=num;
}
}
具体代码如下:
package Test.Date_23_2_13.Test02;
import java.util.LinkedList;
/**
* @ClassName Joker
* @Description TODO
* @Author Love yue yue
* @Date 2023/2/13 11:17
* @Version 1.0
**/
public class Joker {
public static void main(String[] args) throws InterruptedException {
LinkedList<Task> t1 = new LinkedList<Task>();
LinkedList<Task> t2 = new LinkedList<Task>();
LinkedList<Task> t3 = new LinkedList<Task>();
LinkedList<Task> t4 = new LinkedList<Task>();
// for (int i = 0; i < 50000; i++) {
for (int i = 0; i < 500; i++) {
t1.offer(new Task());
}
//启动线程
Task task = new Task();
synchronized (task){//在获取同一个对象锁的时候使用notify和wait
//容量到达目标 启动A线程
if(t1.size() == 500){
new ThreadA_(t1,t2).start();
//容量到达目标 结束A线程
if(t2.size() == 500){
System.out.println("The A end");
return;
}
}
}
//监听线程
//控制台打印
new Thread(){
//匿名内部类
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
//获取当前的队列的容量
int asize = t1.size();
int bsize = t2.size();
int csize = t3.size();
int dsize = t4.size();
System.out.println("队列A:"+asize);
System.out.println("队列B:"+bsize);
System.out.println("队列C:"+csize);
System.out.println("队列D:"+dsize);
System.out.println();
//处理B线程
synchronized (task) {
if (t2.size() == 500) {
new ThreadB_(t2, t3).start();
if(t3.size() == 500) {
System.out.println("The B end");
}
}
}
//处理C线程
synchronized (task) {
if (t3.size() == 500) {
new ThreadC_(t3, t4).start();
if(t4.size() == 500) {
System.out.println("The C end");
}
}
}
//满足结束任务条件 结束任务
if(t1.size() == 0 && t2.size() == 0 && t3.size()==0 && t4.size() ==500){
return;
}
}
}
}.start();
}
}
//线程A
class ThreadA_ extends Thread{
LinkedList<Task> t1;
LinkedList<Task> t2;
public ThreadA_(LinkedList<Task> t1, LinkedList<Task> t2) {
this.t1 = t1;
this.t2 = t2;
}
@Override
public void run() {
// while(true) {
while(true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Task task = t1.poll();
if(t1.size() == 0 && t2.size() == 500){//当线程t1和t2的容量达到相关值停止添加
//此处处理顺序如果在调用方法之后会出现 取不到数据的 会发生NullPointerException异常
break;
}
task.taskA();//调用taskA方法
t2.offer(task);//添加
}
}
}
class ThreadB_ extends Thread{
LinkedList<Task> t2;
LinkedList<Task> t3;
public ThreadB_(LinkedList<Task> t2, LinkedList<Task> t3) {
this.t2 = t2;
this.t3 = t3;
}
@Override
public void run() {
while(true) {
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Task task = t2.poll();
if (t2.size()==0 && t3.size() == 500) break;//处理方式和原理和A线程相似
task.taskB();//调用taskB方法
t3.offer(task);//添加到t3中
}
}
}
class ThreadC_ extends Thread{
LinkedList<Task> t3;
LinkedList<Task> t4;
public ThreadC_(LinkedList<Task> t3, LinkedList<Task> t4) {
this.t3 = t3;
this.t4 = t4;
}
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
Task task = t3.poll();
if(t3.size()==0 && t4.size() == 500) return;//处理方式和原理和A线程相似
task.taskC();//调用taskC方法
t4.offer(task);//添加到t4中
}
}
}
由于本人目前能力有限,发现可能还有更好的方法去处理共享资源,后续会继续跟进的哦,期待大家的关注。