【JAVA】队列

目录

1.同步、异步、阻塞、非阻塞

同步阻塞IO

异步阻塞IO

同步非阻塞IO

异步非阻塞IO

2.java常见队列

3.Queue 

4.队列特性

5.队列接口继承图


1.同步、异步、阻塞、非阻塞

同步和异步是消息通信的机制。

同步:发出一个请求即为一个同步调用。

        (发出请求会得到响应,没有返回响应就会死等结果,需要注意在等待的过程中现成是激活的状态并没有暂停。)

异步:发出一个请求等待结果过程中,可以继续发出后续的请求。

        (这个结果会通过callback、状态或者通知的方式来告知调用方结果。)

异步经历两个步骤:

        1.调用方发起请求,

        2.服务提供方对请求的结果进行返回。

        单看一个请求的发起是同步操作,但是异步主要体现在只要有结果都会通过callback、状态或者通知的方式告知,因此不会存在同步的死等结果。

阻塞和非阻塞是程序在等待调用结果(消息,返回值)时的状态。

阻塞:调用结果返回之前,线程会挂起暂停运行,其他消息用户会进入等待。

非阻塞:调用结果未获取到,不会影响其他运行的线程,知道后面有结果了才会返回。

阻塞和非阻塞最大的区别就是看调用方线程是否会被挂起。

同步阻塞IO

        发出请求,服务提供方未提供结果,线程挂起,直到拿到结果返回,这一个请求才算结束,第二个请求才能进来。

同步:call->retuen

阻塞:等待结果过程中,blocked线程挂起,不能处理别的事情。

如下图所示:

异步阻塞IO

        发出第一个请求,服务提供方立刻返回,未拿到真正调用结果,但是该请求线程会被挂起,等待回调结果。期间可以后续请求,调用过程同样阻塞,直到回调对应结果,结束请求。

异步:call->retuen->callback

阻塞:等待结果过程中,blocked线程挂起,不能处理别的事情。

如下图所示:

同步非阻塞IO

        发出请求,服务提供方立刻返回,没有回调结果,该请求继续call,一直不断地call,直到最总完成结果回调,需要注意在陆续call的过程中,线程未被挂起还是激活状态,可以处理其他事情,像立刻返回请求询问结果等

同步:call->retuen->call->retuen->ccall->callback

阻塞:发出请求,线程激活状态,可以处理别的事情(立刻返回请求的询问结果)。

如下图所示:

异步非阻塞IO

        请求发送出去以后,立刻返回,然后再等待该结果的callback,最后再次请求获取response,这整个过程是异步。

异步:发出请求后,可以继续发出请求。

阻塞:Sender等待callback期间一直是可以处理其它事情的。

如下图所示:

2.java常见队列

ArrayList:可被用作队列,末尾添加和头部删除,但是arrayList是基于数组实现的,因此更适合查询,队列不做推荐。


LinkedList:可用作队列,实现了Deque,继承了Queue接口,LinkedList是基于双向链表实现,使用了指针来链接元素,而不需要移动其他元素。


ArrayBlockingQueue:有界阻塞队列,底层使用数组实现。它有一个固定的容量,并且在插入或删除元素时可能会阻塞线程,直到满足特定的条件。


LinkedBlockingQueue:有界或无界的阻塞队列,底层使用链表实现。


PriorityBlockingQueue:支持优先级的无界阻塞队列。


ConcurrentLinkedQueue:非阻塞无界队列,它适用于多线程环境。它使用链表实现,并且提供了高效的并发操作。

3.Queue 

        队列是一种特殊的线性表,遵循先入先出、后入后出的基本原则,一般来说,它只允许在表的前端进行删除操作,而在表的后端进行插入操作。

import java.util.LinkedList;
import java.util.Queue;

public class QueueTest {
    // 定义队列
    private static Queue<String> queue;
    public static void main(String[] args) {
        getQueue();
//        testRemoveOrPoll();
        testPeekOrElement();
    }

    // 队列中添加元素,返回布尔值
    private static void getQueue() {
        queue = new LinkedList<>();
        // add和offer的区别:offer方法在队列已满时,不会抛出异常,而是返回false,
        // 而add方法在队列已满时或添加失败时候,会抛出异常。
        queue.offer("榴莲");
    }

    // 移除队列首个元素并返回元素
    private static void testRemoveOrPoll(){
        // poll和remove的区别:poll方法在队列为空时,返回null,
        // 而remove方法在队列为空时,会抛出异常'NoSuchElementException'。
        String remove = queue.remove();
        System.out.println(remove);// 输出:榴莲
        String poll = queue.poll();
        System.out.println(poll);// 输出:null
    }

    // 检索返回队列的头元素,但不移除
    private static void testPeekOrElement(){
        // peek和element的区别:peek方法在队列为空时,返回null,而element方法在队列为空时,会抛出异常。
        String peek = queue.element();// 输出:榴莲
        System.out.println(peek);
        String element = queue.element();// 输出:榴莲
        System.out.println(element);
    }
}

4.队列特性

队列主要分为阻塞和非阻塞,有界和无界、单向链表和双向链表

阻塞队列
          入列(添加元素)时,超过队列总数,会进行等待(阻塞),待队列的中的元素出列后,元素数量未超过队列总数时,就会解除阻塞状态,进而可以继续入列;
          出列(删除元素)时,队列为空的情况,也会进行等待(阻塞),待队列有值的时候即会解除阻塞状态,进而继续出列;
          阻塞队列的好处是可以防止队列容器溢出;只要满了就会进行阻塞等待;也就不存在溢出的情况;只要是阻塞队列,都是线程安全的;

阻塞队列提供了以下2个方法:   

        出队阻塞方法 : take() // 添加一个元素,如果队列满,则阻塞
        入队阻塞方法 : put() //  移除并返回队列头部的元素  如果队列为空,则阻塞
                                   drainTo(list)   //一次性取出队列所有元素

非阻塞队列
          不管出列还是入列,都不会进行阻塞。
          入列时,如果元素数量超过队列总数,则会抛出异常,
          出列时,如果队列为空,则取出空值;

有界队列:有界限,大小长度受限制。
无界队列:无限大小,超过界限时就会进行内部动态扩容。
   
单向链表 : 每个元素中除了元素本身之外,还存储一个指针,这个指针指向下一个元素;

双向链表 :除了元素本身之外,还有两个指针,一个指针指向前一个元素的地址,另一个指针指向后一个元素的地址;

5.队列接口继承图

  • 20
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值