首页编程java编程为什么要使用java队列 java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

为什么要使用java队列 java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

编程之家2023-10-1291次浏览

本篇文章给大家谈谈为什么要使用java队列,以及java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么对应的知识点,文章可能有点长,但是希望大家可以阅读完,增长自己的知识,最重要的是希望对各位有所帮助,可以解决了您的问题,不要忘了收藏本站喔。

为什么要使用java队列 java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

java用数组实现队列

1.1.队列的数据结构

队列是一种特殊的线性表,特殊之处在于它只允许在表的前端(front)进行删除操作,而在表的后端(rear)进行插入操作,和栈一样,队列是一种操作受限制的线性表。进行插入操作的端称为队尾,进行删除操作的端称为队头。

1.2. Java实现

为什么要使用java队列 java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

QueueTest

package ch04;

为什么要使用java队列 java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

public class QueueTest{

public static void main(String[] args){

ArrayQueue queue= new ArrayQueue(10);

System.out.println(queue.isEmpty());

for(int i= 0; i< 10; i++){

queue.insert(i);

}

System.out.println(queue.isFull());

while(!queue.isEmpty()){

System.out.println(queue.remove());

}

}

}

class ArrayQueue{

private int[] arrInt;//内置数组

private int front;//头指针

private int rear;//尾指针

public ArrayQueue(int size){

this.arrInt= new int[size];

front= 0;

rear=-1;

}

/**

*判断队列是否为空

*

*@return

*/

public boolean isEmpty(){

return front== arrInt.length;

}

/**

*判断队列是否已满

*

*@return

*/

public boolean isFull(){

return arrInt.length- 1== rear;

}

/**

*向队列的队尾插入一个元素

*/

public void insert(int item){

if(isFull()){

throw new RuntimeException("队列已满");

}

arrInt[++rear]= item;

}

/**

*获得对头元素

*

*@return

*/

public int peekFront(){

return arrInt[front];

}

/**

*获得队尾元素

*

*@return

*/

public int peekRear(){

return arrInt[rear];

}

/**

*从队列的对头移除一个元素

*

*@return

*/

public int remove(){

if(isEmpty()){

throw new RuntimeException("队列为空");

}

return arrInt[front++];

}

}

运行结果如下:

false

true

0

1

2

3

4

5

6

7

8

9

java多线程共同操作同一个队列,怎么实现

以下是两个线程:

import java.util.*;

public class Thread_List_Operation{

//假设有这么一个队列

static List list= new LinkedList();

public static void main(String[] args){

Thread t;

t= new Thread(new T1());

t.start();

t= new Thread(new T2());

t.start();

}

}

//线程T1,用来给list添加新元素

class T1 implements Runnable{

void getElemt(Object o){

Thread_List_Operation.list.add(o);

System.out.println(Thread.currentThread().getName()+"为队列添加了一个元素");

}

@Override

public void run(){

for(int i= 0; i< 10; i++){

getElemt(new Integer(1));

}

}

}

//线程T2,用来给list添加新元素

class T2 implements Runnable{

void getElemt(Object o){

Thread_List_Operation.list.add(o);

System.out.println(Thread.currentThread().getName()+"为队列添加了一个元素");

}

@Override

public void run(){

for(int i= 0; i< 10; i++){

getElemt(new Integer(1));

}

}

}

//结果(乱序)

Thread-0为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-1为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

Thread-0为队列添加了一个元素

java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么

阻塞队列与普通队列的区别在于,当队列是空的时,从队列中获取元素的操作将会被阻塞,或者当队列是满时,往队列里添加元素的操作会被阻塞。试图从空的阻塞队列中获取元素的线程将会被阻塞,直到其他的线程往空的队列插入新的元素。同样,试图往已满的阻塞队列中添加新元素的线程同样也会被阻塞,直到其他的线程使队列重新变得空闲起来,如从队列中移除一个或者多个元素,或者完全清空队列.

1.ArrayDeque,(数组双端队列)

2.PriorityQueue,(优先级队列)

3.ConcurrentLinkedQueue,(基于链表的并发队列)

4.DelayQueue,(延期阻塞队列)(阻塞队列实现了BlockingQueue接口)

5.ArrayBlockingQueue,(基于数组的并发阻塞队列)

6.LinkedBlockingQueue,(基于链表的FIFO阻塞队列)

7.LinkedBlockingDeque,(基于链表的FIFO双端阻塞队列)

8.PriorityBlockingQueue,(带优先级的无界阻塞队列)

9.SynchronousQueue(并发同步阻塞队列)

阻塞队列和生产者-消费者模式

阻塞队列(Blocking queue)提供了可阻塞的put和take方法,它们与可定时的offer和poll是等价的。如果Queue已经满了,put方法会被阻塞直到有空间可用;如果Queue是空的,那么take方法会被阻塞,直到有元素可用。Queue的长度可以有限,也可以无限;无限的Queue永远不会充满,所以它的put方法永远不会阻塞。

阻塞队列支持生产者-消费者设计模式。一个生产者-消费者设计分离了“生产产品”和“消费产品”。该模式不会发现一个工作便立即处理,而是把工作置于一个任务(“to do”)清单中,以备后期处理。生产者-消费者模式简化了开发,因为它解除了生产者和消费者之间相互依赖的代码。生产者和消费者以不同的或者变化的速度生产和消费数据,生产者-消费者模式将这些活动解耦,因而简化了工作负荷的管理。

生产者-消费者设计是围绕阻塞队列展开的,生产者把数据放入队列,并使数据可用,当消费者为适当的行为做准备时会从队列中获取数据。生产者不需要知道消费者的省份或者数量,甚至根本没有消费者—它们只负责把数据放入队列。类似地,消费者也不需要知道生产者是谁,以及是谁给它们安排的工作。BlockingQueue可以使用任意数量的生产者和消费者,从而简化了生产者-消费者设计的实现。最常见的生产者-消费者设计是将线程池与工作队列相结合。

阻塞队列简化了消费者的编码,因为take会保持阻塞直到可用数据出现。如果生产者不能足够快地产生工作,让消费者忙碌起来,那么消费者只能一直等待,直到有工作可做。同时,put方法的阻塞特性也大大地简化了生产者的编码;如果使用一个有界队列,那么当队列充满的时候,生产者就会阻塞,暂不能生成更多的工作,从而给消费者时间来赶进进度。

有界队列是强大的资源管理工具,用来建立可靠的应用程序:它们遏制那些可以产生过多工作量、具有威胁的活动,从而让你的程序在面对超负荷工作时更加健壮。

虽然生产者-消费者模式可以把生产者和消费者的代码相互解耦合,但是它们的行为还是间接地通过共享队列耦合在一起了

类库中包含一些BlockingQueue的实现,其中LinkedBlockingQueue和ArrayBlockingQueue是FIFO队列,与 LinkedList和ArrayList相似,但是却拥有比同步List更好的并发性能。PriorityBlockingQueue是一个按优先级顺序排序的队列,当你不希望按照FIFO的属性处理元素时,这个PriorityBolckingQueue是非常有用的。正如其他排序的容器一样,PriorityBlockingQueue可以比较元素本身的自然顺序(如果它们实现了Comparable),也可以使用一个 Comparator进行排序。

最后一个BlockingQueue的实现是SynchronousQueue,它根本上不是一个真正的队列,因为它不会为队列元素维护任何存储空间。不过,它维护一个排队的线程清单,这些线程等待把元素加入(enqueue)队列或者移出(dequeue)队列。因为SynchronousQueue没有存储能力,所以除非另一个线程已经准备好参与移交工作,否则put和take会一直阻止。SynchronousQueue这类队列只有在消费者充足的时候比较合适,它们总能为下一个任务作好准备。

非阻塞算法

基于锁的算法会带来一些活跃度失败的风险。如果线程在持有锁的时候因为阻塞I/O,页面错误,或其他原因发生延迟,很可能所有的线程都不能前进了。

一个线程的失败或挂起不应该影响其他线程的失败或挂起,这样的算法成为非阻塞(nonblocking)算法;如果算法的每一个步骤中都有一些线程能够继续执行,那么这样的算法称为锁自由(lock-free)算法。在线程间使用CAS进行协调,这样的算法如果能构建正确的话,它既是非阻塞的,又是锁自由的。非竞争的CAS总是能够成功,如果多个线程以一个CAS竞争,总会有一个胜出并前进。非阻塞算法堆死锁和优先级倒置有“免疫性”(但它们可能会出现饥饿和活锁,因为它们允许重进入)。

非阻塞算法通过使用低层次的并发原语,比如比较交换,取代了锁。原子变量类向用户提供了这些底层级原语,也能够当做“更佳的volatile变量”使用,同时提供了整数类和对象引用的原子化更新操作

为什么要使用java队列和java 中 阻塞队列 非阻塞队列 和普通队列的区别是什么的问题分享结束啦,以上的文章解决了您的问题吗?欢迎您下次再来哦!

境外汇款手续费(中国银行境外汇款手续费)java和区别是什么意思,JAVA和JAVE分别是什么意思有什么区别