Wend看源码-Java-集合学习(Queue)
概述
Wend看源码-Java-集合学习(List)-CSDN博客
Wend看源码-Java-集合学习(Set)-CSDN博客
在前两篇文章中,我们分别探讨了Java集合框架的父类以及List集合和Set集合的实现。接下来,本文将重点阐述Java中的Queue集合,包括其内部的数据结构以及核心方法的详尽说明。
Queue 集合
图1 Java-queue类型数据结构类图(基本)
图2 Java-Queue类型数据结构类图(线程安全的)
如图1、图2 所示,Queue 接口继承自Collection 接口,而Queue 数据类型的实现,以及Deque 数据类型的实现均需要继承Queue 接口。Queue它用于表示一种队列数据结构,遵循先进先出(FIFO-First-In-First-Out)的原则。就像在生活中排队一样,先进入队列的元素先被取出。这种数据结构在很多场景下都非常有用,例如任务调度、消息传递等。
Queue 接口
以下是Queue接口的主要方法列表:
- add:尝试将指定元素插入到队列中。该方法遵循这样的规则,如果队列当前有足够的空间(对于有容量限制的队列而言),且元素符合队列对元素类型等各方面要求,那么插入操作会成功,并且返回
true
。但如果队列已满,无法再容纳新元素了,此时该方法会抛出IllegalStateException
异常来表明插入失败。 offer:
同样是用于向队列中插入指定元素,不过和add
方法有所区别。在插入时,如果队列有容量限制且当前已满,它不会抛出异常,而是直接返回false
,表示插入元素的操作没有成功;只有在元素成功插入到队列后,才会返回true
。所以在使用有容量限制的队列时,该方法相比add
方法在处理插入失败情况时更加 “温和”,不会因插入失败而中断程序流程(抛出异常)。remove:
用于从队列中移除并返回队列头部(也就是最先进入队列的那个元素,遵循先进先出原则)的元素。但要注意,如果当前队列为空,也就是没有元素可供移除时,该方法会抛出NoSuchElementException
异常,以此提示调用者队列中无元素可操作。poll:
也是用于移除并返回队列头部的元素,不过它和remove()
方法的区别在于对队列为空情况的处理方式。当队列为空时,它不会抛出异常,而是直接返回null
,这样使得调用者可以通过判断返回值是否为null
来知晓队列是否为空以及操作是否成功获取到了元素,使用起来更加灵活,在一些需要避免异常处理逻辑复杂的场景中较为实用。- element:用于返回队列的头部元素,但它并不会将这个元素从队列中移除,也就是仅仅查看队列头部是谁。不过当队列为空时,它会抛出
NoSuchElementException
异常,和remove()
方法对空队列的处理类似,使用该方法时需要确保队列中有元素,否则要做好异常处理准备。 - peek:同样是返回队列的头部元素且不做移除操作,与
element()
方法不同的是,当队列为空时,它不会抛出异常,而是返回null
。这样方便调用者通过简单判断返回值来知晓队列的状态以及获取头部元素情况,避免了异常处理的复杂性,在很多场景下代码逻辑会更简洁。
AbstractQueue
AbstractQueue 是一个抽象类,它实现了 Queue 接口。它位于 Java 集合框架中,主要目的是为 Queue 接口提供部分通用的实现方法,方便其他类继承并实现自己的队列功能。它减少了实现 Queue 接口的工作量,通过提供一些基础的方法实现和定义必要的抽象方法,引导子类去完善队列的具体功能。
PriorityQueue
PriorityQueue 是一个优先级队列,它实现了 Queue 接口,用于维护一个具有优先级顺序的元素集合。它的内部是通过一个可动态调整大小的数组来实现的,元素会根据一定的优先级规则进行排序。这个优先级规则可以是元素的自然顺序(如果元素实现了 Comparable 接口),或者是通过一个自定义的 Comparator 来确定。
主要特点
- 优先级排序:元素在队列中是按照优先级顺序排列的。例如,对于存储整数的 PriorityQueue,如果按照默认的自然顺序(从小到大)作为优先级,那么每次调用 poll 方法移除的元素都是当前队列中最小的整数。如果通过自定义 Comparator 改变了优先级规则,比如定义一个从大到小的比较器,那么每次移除的元素就是当前队列中最大的整数。
- 插入元素时,也会根据优先级规则找到合适的位置插入。例如,在一个存储自定义任务对象的 PriorityQueue 中,每个任务有一个优先级属性,当插入一个新任务时,它会根据任务的优先级在队列中找到合适的位置插入,使得队列始终保持优先级顺序。
- 动态调整大小:它的内部数组会根据元素数量的变化自动调整大小。当元素数量达到一定阈值时,数组会进行扩容操作,以容纳更多的元素。这个过程对用户是透明的,不需要手动干预。例如,当不断向一个 PriorityQueue 中添加元素,它会自动增加内部数组的容量来存储新元素。
应用场景
- 任务调度:在操作系统的任务调度或者分布式系统的任务处理中,PriorityQueue 可以用来存储任务,按照任务的优先级进行调度。例如,高优先级的任务可以先被处理,通过将任务插入到 PriorityQueue 中,系统可以方便地获取优先级最高的任务进行处理。
- 数据排序和筛选:可以用于对数据进行排序和筛选。例如,在一个数据处理系统中,有一批数据对象,每个对象有一个权重属性,通过将这些数据对象放入 PriorityQueue 中,按照权重进行排序,然后可以方便地获取权重最高或最低的数据对象,用于进一步的分析和处理。
线程安全的 Queue
BlockingQueue 接口
BlockingQueue
是一个位于java.util.concurrent
包中的接口,它是为了解决多线程环境下生产者 - 消费者问题而设计的。它在普通队列(Queue
)的基础上增加了阻塞特性,当队列满时,生产者线程插入元素的操作会被阻塞;当队列空时,消费者线程获取元素的操作会被阻塞。这使得在多线程场景下可以方便地协调数据的生产和消费,避免了频繁地检查队列状态(如使用非阻塞队列时,需要不断检查队列是否为空或已满)。
应用场景
在多线程的消息队列系统中,生产者线程将消息放入BlockingQueue
,消费者线程从队列中获取消息进行处理。这种阻塞机制保证了消息的生产和消费能够有条不紊地进行,不会因为队列状态(满或空)而出现数据丢失或线程过度占用资源的情况。
ArrayBlockingQueue
ArrayBlockingQueue
是BlockingQueue
接口的一个实现类,它基于数组来实现阻塞队列。在创建时需要指定队列的容量,这个容量一旦确定就不能改变。它内部通过一个数组来存储元素,并且维护了两个指针(索引),一个用于记录队列头部元素的位置,一个用于记录队列尾部元素的位置,通过移动这些指针来实现元素的添加和移除操作。
主要特点
-
有界性:由于基于固定大小的数组,它是有界的,队列容量在创建时就固定了。例如,
ArrayBlockingQueue<Integer> queue = new ArrayBlockingQueue<>(10);
创建了一个容量为 10 的整数队列。 -
公平性选项:在构造方法中可以指定是否为公平队列。公平队列会按照线程等待的先后顺序来访问队列,而非公平队列则不保证这一点,可能会出现后来的线程先访问队列的情况。例如,
ArrayBlockingQueue<String> fairQueue = new ArrayBlockingQueue<>(5, true);
创建了一个公平的字符串队列。
应用场景
适用于需要限制队列大小的生产者 - 消费者场景,如在一个资源有限的系统中,对产生的数据进行缓存和处理。比如,一个服务器接收客户端请求,将请求放入ArrayBlockingQueue
,然后由固定数量的工作线程从队列中获取请求进行处理,通过限制队列大小可以避免服务器内存被过多的请求耗尽。
LinkedBlockingQueue
LinkedBlockingQueue
也是BlockingQueue
接口的实现类,它基于链表结构来实现阻塞队列。与ArrayBlockingQueue
不同,它的容量可以在构造时指定,如果不指定容量,则默认为Integer.MAX_VALUE
,实际上相当于无界队列(但受系统资源限制)。它通过链表节点来存储元素,添加和移除元素时操作链表的节点。
主要特点
-
可选有界性:可以根据需要创建有界或无界队列。例如,
LinkedBlockingQueue<Double> boundedQueue = new LinkedBlockingQueue<>(100);
创建了一个容量为 100 的有界双精度浮点数队列,而LinkedBlockingQueue<String> unboundedQueue = new LinkedBlockingQueue<>();
创建了一个默认无界的字符串队列。 -
高并发性能:在高并发场景下,基于链表的实现方式使得它在插入和移除元素时的性能相对较好,因为链表的节点添加和删除操作在并发环境下对锁的竞争相对较小(相比于数组可能需要对整个数组进行锁定的情况)。
应用场景
在高并发的生产者 - 消费者场景中,当需要处理大量的数据并且对队列大小不太确定或者希望有较大的缓冲空间时,LinkedBlockingQueue
是一个很好的选择。例如,在一个大规模的数据采集系统中,采集到的数据可以放入LinkedBlockingQueue
,然后由多个数据处理线程从队列中获取数据进行处理,由于其高并发性能和可选的无界特性,可以更好地适应数据流量的波动。
SynchronousQueue
SynchronousQueue
是一种特殊的BlockingQueue
实现,它没有内部容量来存储元素。它的作用是作为一个同步点,用于线程之间的直接数据传递。当一个线程调用put
方法尝试放入元素时,这个操作会阻塞,直到有另一个线程调用take
方法来获取这个元素;反之,当一个线程调用take
方法时,会阻塞直到有其他线程放入元素。
主要特点
-
无存储容量:这是它最显著的特点,使得它更像是一个线程之间的同步工具,而不是传统意义上的队列用于存储元素。例如,在一个简单的线程通信场景中,一个线程生产的数据必须立即被另一个线程消费,就可以使用
SynchronousQueue
。 -
公平性和非公平性选项:和
ArrayBlockingQueue
类似,在构造方法中可以指定公平性选项,影响线程获取元素的顺序。
应用场景
适用于线程之间需要紧密同步传递数据的场景,如在一个高性能的线程池实现中,任务的提交和执行线程之间可以使 用SynchronousQueue
来确保任务被立即执行,而不会在队列中等待。或者在一个简单的两线程通信场景中,一个线程生成的数据要直接交给另一个线程进行处理,避免中间存储。
DelayedQueue
DelayedQueue
是一个支持延迟获取元素的无界阻塞队列,它实现了BlockingQueue
接口并且存储的元素必须实现Delayed
接口。Delayed
接口要求实现类定义一个获取剩余延迟时间的方法(getDelay
)和一个比较方法(compareTo
),用于确定元素的延迟顺序。DelayedQueue
内部会根据元素的延迟时间来排序元素,只有当元素的延迟时间到期后,才能从队列中获取该元素。
主要特点
-
延迟特性:元素在放入队列后,不会立即被获取,而是要等待延迟时间结束。例如,在一个定时任务调度系统中,可以将任务放入
DelayedQueue
,每个任务有自己的执行时间(延迟时间),队列会根据任务的执行时间来安排任务的获取顺序。 -
排序依据延迟时间:内部按照元素的延迟时间进行排序,延迟时间短的元素会排在队列头部(更接近可以被获取的状态)。这是通过
Delayed
接口的compareTo
方法来实现的,确保了队列中元素的顺序符合延迟时间的要求。
应用场景
用于实现定时任务调度系统、缓存过期策略等场景。例如,在一个缓存系统中,缓存对象可以实现Delayed
接口,设置缓存的过期时间作为延迟时间,放入DelayedQueue
。当缓存过期时,从队列中获取到该缓存对象,然后进行清理操作。
PriorityBlockingQueue
PriorityBlockingQueue
是一个支持优先级的无界阻塞队列,它实现了BlockingQueue
接口。内部是通过一个可动态调整大小的数组来实现的,元素按照优先级顺序排列,优先级可以通过元素的自然顺序(如果元素实现了Comparable
接口)或者通过提供的Comparator
来确定。它在多线程环境下是线程安全的,多个线程可以同时对队列进行操作。
主要特点
-
优先级排序:和
PriorityQueue
类似,元素在队列中按照优先级顺序存储和获取。例如,在一个任务管理系统中,任务可以根据重要性或者紧急程度设置优先级,放入PriorityBlockingQueue
后,高优先级的任务会先被获取和处理。 -
无界性和动态调整大小:它是无界的,内部数组会根据元素数量自动调整大小,这使得它可以存储大量的元素,但也需要注意可能导致的内存问题。
-
线程安全:在多线程环境下,多个线程可以安全地插入和获取元素,这是通过内部的锁机制和并发控制来实现的。
应用场景
适用于多线程环境下需要按照优先级处理任务或元素的场景,如操作系统中的进程调度、分布式系统中的任务分发等。例如,在一个分布式计算系统中,不同的计算任务有不同的优先级,将这些任务放入PriorityBlockingQueue
,工作节点可以从队列中获取高优先级的任务先进行处理,提高系统的整体效率。
TransferQueue 接口
TransferQueue
是 Java 中的一个接口,它继承自BlockingQueue
接口。这个接口主要用于在生产者 - 消费者模式中实现元素的转移。它允许生产者线程在队列满时等待消费者线程接收元素,而不是简单地阻塞或者抛出异常。
-
transfer方法
:这是TransferQueue
接口的核心方法。生产者线程调用这个方法来传递一个元素e
给消费者线程。如果此时有消费者线程正在等待接收元素,那么这个元素会立刻被传递给消费者;如果没有消费者在等待,那么生产者线程会被阻塞,直到有消费者来接收这个元素。
应用场景
适用于生产者和消费者之间需要紧密同步的场景。例如,在一个多线程的消息传递系统中,当一个消息生产者产生了一个重要消息,它希望确保这个消息能被消费者立即处理,就可以使用TransferQueue
。
LinkedTransferQueue
LinkedTransferQueue
是TransferQueue
接口的一个实现类,它是基于链表结构实现的无界队列。它在性能上表现良好,特别是在高并发环境下,能够有效地处理元素的插入和移除操作。
特点
-
无界性:它的容量没有固定限制,可以不断地添加元素。不过,如果生产者的速度远远超过消费者的速度,可能会导致内存占用过高。
-
高效性:基于链表的实现使得元素的插入和移除操作在并发环境下具有较高的效率。在添加元素时,只需要对链表的节点进行操作,不需要像数组那样进行扩容等复杂操作。
-
公平性:
LinkedTransferQueue
支持公平和非公平两种模式。在公平模式下,线程按照它们请求操作的顺序(例如调用transfer
方法的顺序)来访问队列;在非公平模式下,不保证这种顺序,新到达的线程可能会先于等待时间较长的线程访问队列。
应用场景
LinkedTransferQueue
适合在高并发的生产者 - 消费者场景中使用,例如在多线程的任务调度系统中,任务生产者将任务放入LinkedTransferQueue
,任务消费者从队列中获取任务并执行。由于其无界性和高效性,可以有效地处理大量的任务。
ConcurrentLinkedQueue
ConcurrentLinkedQueue
是一个线程安全的队列,它实现了Queue
接口。这个队列是基于链表实现的无界队列,它采用了一种高效的非阻塞算法来保证在并发环境下的正确操作。
特点
-
线程安全:它通过使用 CAS(Compare - And - Swap)操作来实现线程安全。在多个线程同时访问队列时,能够正确地处理元素的插入和移除操作,不会出现数据不一致的情况。
-
无界性:它的容量没有限制,可以容纳任意数量的元素。
-
弱一致性迭代器:
ConcurrentLinkedQueue
的迭代器是弱一致性的。这意味着在迭代过程中,如果队列被其他线程修改,迭代器可能不会反映这些修改,但是它不会抛出ConcurrentModificationException
。
应用场景
适用于多个生产者和多个消费者并发访问的场景,例如在分布式系统中的消息队列中间件的本地缓存队列,或者在多线程的日志收集系统中,多个线程可以安全地将日志消息添加到ConcurrentLinkedQueue
中,然后由其他线程从队列中读取并处理这些消息。
Deque 接口
Deque
(双端队列)接口继承自Queue
接口和SequencedCollection
接口,它代表的是一种支持在两端进行元素插入和移除操作的线性集合。
Deque 接口分为两种方法,分别是队首操作和队尾操作的方法,其中包括:
队首操作方法
-
addFirst:
尝试将指定元素e
插入到此双端队列的前端,如果由于容量限制等原因无法立即插入,会抛出IllegalStateException
异常。例如,在有容量限制且已满的双端队列上调用此方法就会抛异常。 -
offerFirst:
将指定元素e
插入到此双端队列的前端,除非这样做会违反容量限制。如果插入成功返回true
,否则返回false
。在使用有容量限制的双端队列时,相较于addFirst
方法更合适,因为addFirst
只能通过抛异常来表示插入失败。 -
removeFirst:
检索并移除双端队列的第一个元素,如果队列为空则抛出NoSuchElementException
异常。 -
pollFirst:
检索并移除双端队列的第一个元素,如果双端队列为空则返回null
-
getFirst:
检索但不移除此双端队列的第一个元素,如果双端队列为空则抛出NoSuchElementException
异常。 -
peekFirst:
检索但不移除此双端队列的第一个元素,如果双端队列为空则返回null
队尾操作方法
-
addLast:
尝试将指定元素e
插入到此双端队列的末尾。如果由于容量限制等原因无法立即插入,会抛出IllegalStateException
异常。此方法等同于add
方法。 -
offerLast:
将指定元素e
插入到此双端队列的末尾,除非这样做会违反容量限制,插入成功返回true
,否则返回false
。在使用有容量限制的双端队列时,相较于addLast
更合适。 -
removeLast:
检索并移除双端队列的最后一个元素,如果队列为空则抛出NoSuchElementException
异常。 -
pollLast:
检索并移除双端队列的最后一个元素,如果双端队列为空则返回null
。 -
getLast:
检索但不移除此双端队列的最后一个元素,如果双端队列为空则抛出NoSuchElementException
异常。 -
peekLast:
检索但不移除此双端队列的最后一个元素,如果双端队列为空则返回null
。
使用特点与应用场景
- 作为队列(FIFO - 先进先出)使用时:元素添加到双端队列的末尾(调用
addLast
、offerLast
等方法),从头部移除(调用removeFirst
、pollFirst
等方法),可以替代传统的Queue
实现类,用于需要按顺序处理元素的场景,比如任务队列,按照任务添加的顺序依次执行任务。 - 作为栈(LIFO - 后进先出)使用时:元素在双端队列的头部进行压入(调用
push
或addFirst
方法)和弹出(调用pop
或removeFirst
方法)操作,相比传统的Stack
类,Deque
接口提供了更灵活且线程安全的栈操作实现方式,适用于方法调用栈模拟、表达式求值等需要后进先出逻辑的场景。
ArrayDeque
ArrayDeque
是一种基于数组的双端队列。这意味着它可以高效地在两端进行插入和删除操作,并且具有动态调整大小的能力。它是一种非线程安全的集合类,如果需要在多线程环境下使用,可以通过适当的同步措施(如使用Collections.synchronizedDeque
方法)来确保线程安全。
数据结构
ArrayDeque
内部使用一个数组来存储元素。它有两个指针,分别指向队列的头部和尾部,这样就可以方便地在两端进行操作。当元素被添加到头部或尾部时,指针会相应地移动。
例如,在初始状态下,队列为空,头指针和尾指针都指向数组的起始位置。当添加一个元素到头部时,头指针会向左移动(如果数组是循环使用的话),然后将元素放置在新的头指针位置;添加元素到尾部时,尾指针向右移动,元素放置在尾指针位置。
线程安全的 Deque
BlockingDeque
BlockingDeque
是 Java 中的一个接口,它继承自Deque
和BlockingQueue
接口。这个接口在双端队列的基础上,提供了阻塞式的操作方法,主要用于在多线程环境下实现生产者 - 消费者模式等场景,使得线程在队列满或空时能够阻塞等待,而不是直接返回错误或异常。
应用场景
适合用于需要在多线程环境下,对双端队列进行安全且阻塞式操作的场景。比如在一个多线程的消息传递系统中,消息生产者和消费者通过BlockingDeque
进行通信,当没有消息时消费者阻塞等待,当队列满时生产者阻塞等待。
LinkedBlockingDeque
LinkedBlockingDeque
是BlockingDeque
接口的一个实现类,它基于链表结构实现阻塞式双端队列。它的容量可以在初始化时指定,如果不指定容量,默认是Integer.MAX_VALUE
,也就是一个无界队列。
特点
-
链表结构的优势:基于链表实现使得它在插入和删除操作时比较灵活,不需要像数组那样考虑扩容和元素移动的问题。在并发环境下,多个线程对队列两端进行操作时,链表结构能够有效地减少锁竞争,提高并发性能。
-
阻塞操作的实现:通过内部的锁和条件队列(
Condition
)来实现阻塞式操作。当队列满或空时,线程会在相应的条件队列中等待,直到其他线程执行了相应的插入或移除操作,唤醒等待的线程。 -
容量灵活性:可以根据实际需求在初始化时设定容量。如果确定是有界队列场景,设定合适的容量可以避免过度占用内存。
应用场景
适用于高并发的生产者 - 消费者场景,特别是当生产者和消费者的速度可能不一致,且需要保证在队列满或空时线程能够正确等待的情况。例如在一个多线程的文件读取和处理系统中,文件读取线程作为生产者将读取到的文件内容放入LinkedBlockingDeque
,文件处理线程作为消费者从队列中获取内容进行处理。
ConcurrentLinkedDeque
ConcurrentLinkedDeque
是一个线程安全的双端队列,它实现了Deque
接口。它是基于链表的无界队列,采用非阻塞算法(主要是通过 CAS 操作)来保证在并发环境下的操作正确性。
特点
-
线程安全的非阻塞实现:它使用 CAS(Compare - And - Swap)操作来实现多线程环境下的并发控制。CAS 操作是一种乐观锁机制,在更新元素时会先比较当前值与预期值,如果相同则更新,不同则表示有其他线程已经修改了该值,此时会重试操作。这种方式避免了传统锁机制可能带来的线程阻塞和性能下降问题。
-
无界性和动态性:作为无界队列,它可以容纳任意数量的元素,不会因为队列满而拒绝插入元素。并且其链表结构使得它能够动态地适应元素数量的变化。
-
弱一致性迭代器:
ConcurrentLinkedDeque
的迭代器是弱一致性的。这意味着在迭代过程中,如果队列被其他线程修改,迭代器可能不会反映这些修改,但是它不会抛出ConcurrentModificationException
。
应用场景
适用于高并发的场景,特别是多个生产者和多个消费者同时对双端队列进行操作的情况。例如在分布式系统中的消息中间件,多个生产者可以将消息发送到ConcurrentLinkedDeque
作为本地缓存队列,多个消费者可以同时从队列中获取消息进行处理,而且不用担心线程阻塞问题,能够高效地处理大量消息。
参考文献
豆包
相关文章推荐
Wend看源码-Java-集合学习(List)-CSDN博客
Wend看源码-Java-集合学习(Set)-CSDN博客
相关文章:
Wend看源码-Java-集合学习(Queue)
概述 Wend看源码-Java-集合学习(List)-CSDN博客 Wend看源码-Java-集合学习(Set)-CSDN博客 在前两篇文章中,我们分别探讨了Java集合框架的父类以及List集合和Set集合的实现。接下来,本文将重点阐述Java中的Queue集合,包括其内部的数据结…...
大数据面试笔试宝典之HBase面试
1.HBase 数据存储位置 HBase 中的数据存储在哪里? 以什么格式存储?和 Zookeeper 什么关系? 参考答案: 1.HBase 中的所有数据文件都存储在 Hadoop HDFS 文件系统上。 2.包含两种文件类型: HFile : HBase 中 KeyValue 数据的存储格式。HFile 是 Hadoop 的二进制格式文件…...
React基础知识学习
学习React前端框架是一个系统而深入的过程,以下是一份详细的学习指南: 一、React基础知识 React简介 React是一个用于构建用户界面的JavaScript库,由Facebook开发和维护。它强调组件化和声明式编程,使得构建复杂的用户界面变得更…...
实战指南:Shiro、CAS打造完美单点登录体验
引言 想象一下,在日常工作中,我们经常需要进行系统认证和授权。当用户尝试登录一个网站时,他们需要提供用户名和密码,网站会检查这些信息,确认用户是谁。这就是认证的过程。 一旦用户被认证,他们可能会尝…...
光储充一体化解决方案详解。
一、光储充介绍 1、什么是光储充 “光储充”一体化,顾名思义,是由光伏发电、储能、充电集成一体、互相协调支撑的绿色充电模式。其工作原理是利用光伏发电,余电由储能设备存储,共同承担供电充电任务。在用电高峰,光储…...
TDengine 新功能 VARBINARY 数据类型
1. 背景 VARBINARY 数据类型用于存储二进制数据,与 MySQL 中的 VARBINARY 数据类型功能相同,VARBINARY 数据类型长度可变,在创建表时指定最大字节长度,使用进按需分配存储,但不能超过建表时指定的最大值。 2. 功能说明…...
2024年秋词法分析作业(满分25分)
【问题描述】 请根据给定的文法设计并实现词法分析程序,从源程序中识别出单词,记录其单词类别和单词值,输入输出及处理要求如下: (1)数据结构和与语法分析程序的接口请自行定义;类别码需按下表格…...
AF3 checkpoint_blocks函数解读
checkpoint_blocks 函数实现了一种分块梯度检查点机制 (checkpoint_blocks),目的是通过分块(chunking)执行神经网络模块,减少内存使用。在深度学习训练中,梯度检查点(activation checkpointing)是一种显存优化技术。该代码可以: 对神经网络的块(blocks)按需分块,并对…...
VITUREMEIG | AR眼镜 算力增程
根据IDC发布的《2024年第三季度美国AR/VR市场报告》显示,美国市场AR/VR总出货量增长10.3%。其中,成立于2021年的VITURE增长速度令人惊艳,同比暴涨452.6%,成为历史上增长最快的AR/VR品牌。并在美国AR领域占据了超过50%的市场份额&a…...
详解MySQL在Windows上的安装
目录 查看电脑上是否安装了MySQL 下载安装MySQL 打开MySQL官网,找到DOWNLOADS 然后往下翻,找到MySQL Community(GPL) Downloads>> 然后找到MySQL Community Server 然后下载,选择No thanks,just start my download. 然后双击进行…...
细说STM32F407单片机CAN基础知识及其HAL驱动程序
目录 一、CAN总线结构和传输协议 1、 CAN总线结构 (1)闭环结构的CAN总线网络 (2)开环结构的CAN总线网络 (3)隐性电平和显性电平 2、CAN总线传输协议 (1)CAN总线传输特点 &am…...
Ubuntu 22.04 升级 24.04 问题记录
一台闲置笔记本使用的 ubuntu 还是 18.04,最近重新使用,发现版本过低,决定升级,于是完成了 18.04 -> 20.04 -> 22. 04 -> 24.04 的三连跳。 一、升级过程中黑屏 主要问题是在 22.04 升级到 24.04 过程中出现了黑屏仅剩…...
模型选择+过拟合欠拟合
训练误差和泛化误差 训练误差:模型在训练数据上的误差 泛化误差:模型在新数据上的误差 验证数据集:一个用来评估模型好坏的数据集 例如拿出50%的数据作为训练 测试数据集:只能用一次 K则交叉验证 在没有足够数据时使用 算法…...
Leetcode 3404. Count Special Subsequences
Leetcode 3404. Count Special Subsequences 1. 解题思路2. 代码实现 题目链接:3404. Count Special Subsequences 1. 解题思路 这道题是事实上这次的周赛最难的一道题目,不过也是有点巧思在内。 最开始我的想法就是按照乘积构成pair,然后…...
萌萌哒的八戒
萌萌哒的八戒 下载压缩包后,打开发现有一张照片 既然是关于猪的,那就用猪圈密码解码 flag{whenthepigwanttoeat}...
开启家具组装新方式:产品说明书智能指导
在快节奏的现代生活中,人们越来越追求便捷与高效。无论是新房装修还是家具换新,家具组装已成为许多家庭不可避免的一项任务。然而,面对复杂多变的家具图纸和冗长的产品说明书,许多人常常感到无从下手,甚至因操作不当而…...
【连续学习之ResCL算法】2020年AAAI会议论文:Residual continual learning
1 介绍 年份:2020 会议: AAAI Lee J, Joo D, Hong H G, et al. Residual continual learning[C]//Proceedings of the AAAI Conference on Artificial Intelligence. 2020, 34(04): 4553-4560. 本文提出的算法是Residual Continual Learning (ResC…...
【网络协议】路由信息协议 (RIP)
未经许可,不得转载。 路由信息协议(Routing Information Protocol,简称 RIP)是一种使用跳数(hop count)作为路由度量标准的路由协议,用于确定源网络和目标网络之间的最佳路径。 文章目录 什么是…...
Linux 终端查看 nvidia 显卡型号
文章目录 写在前面1. 需求描述2. 实现方法方法一:方法二方法三: 参考链接 写在前面 自己的测试环境: Ubuntu20.04 1. 需求描述 Linux 终端查看 nvidia 显卡型号 2. 实现方法 方法一: 执行下列指令: sudo update…...
基于neurokit2的心电仿真数据生成实例解析
一 概念 NeuroKit2是一个开源的、社区驱动的、以用户为中心的Python库,可用于多种生理信号的分析处理(例如ECG、PPG、EDA、EMG、RSP),还包括用于特定处理步骤(如频率)的工具提取和过滤方法,并在…...
AMBA-APB
目录 1.APB 协议 2.APB信号列表 3.数据传输 3.1写传输(2种) 3.1.1 无等待状态的写传输 3.1.2有等待状态的写传输 3.2写选通信号 (PSTRB) 字节通道映射 3.3读传输(2种) 3.3.1 无等待状态的读传输 3.3.2有等待状态的读传…...
网安入门之PHP后端基础
PHP 基本概念详解 PHP是一种服务器端脚本语言,常用于动态网站开发和 web 应用程序。以下是 PHP 的基本概念与特点的详细说明: 1. PHP 文件的默认文件扩展名 PHP 文件的扩展名通常为 .php,例如 index.php。PHP 文件可以包含 PHP 代码、HTML…...
windows系统安装完Anaconda之后怎么激活自己的虚拟环境并打开jupyter
1.在win主菜单中找到Anaconda安装文件夹并打开终端 文件夹内有所有安装后的Anaconda的应用软件和终端窗口启动窗口 点击Anaconda Prompt(Anaconda)就会打开类似cmd的命令终端窗口,默认打开的路径是用户名下的路径 2.激活虚拟环境 使用命令…...
【C#特性整理】C#特性及语法基础
1. C#特性 1.1 统一的类型系统 C#中, 所有类型都共享一个公共的基类型. 例如,任何类型的实例都可以通过调用ToString方法将自身转换为一个字符串 1.2 类和接口 接口: 用于将标准与实现隔离, 仅仅定义行为,不做实现. 1.3 属性、方法、事件 属性: 封装了一部分对…...
龙蜥 配置本地yum源8.6----亲测
系统版本: 说明:丫丫的,内网服务安装了个龙蜥操作系统。内网不能访问互联网,所以就需要挂载yum源 用的以前的方法挂载,一直报错 [Couldnt open file /mnt/anolisos/repodata/repomd.xml] yum挂载的时候报错,奇葩!!!,龙蜥的挂载方法好像不一样。 解决: 一、上传并挂…...
Xshell日志录制
步骤 1:设置日志文件位置 打开 Xshell 软件,选择目标会话(或者创建一个新的会话)。右键点击会话名称,选择“属性”。在会话属性窗口中,找到“日志”选项卡。勾选“启用日志记录”。在“文件名”中设置日志…...
vue下载和上传的地址动态ip地址配置方法
vue3结合element-plus实现【下载文件】和【上传文件】的动态ip地址配置 效果图 一、修改【文件上传】静态地址 1、首先引入axios import axios from "/utils/request"; import { getToken } from "/utils/auth"; 定义 const importDialogVisible ref(…...
动手做计算机网络仿真实验入门学习
打开软件 work1 添加串行接口模块,先关电源,添加之后再开电源 自动选择连接 所有传输介质 自动连接 串行线 绿色是通的,红色是不通的。 显示接口。se是serial串行的简写。 Fa是fast ethernet的简写。 为计算机配置ip地址: 为服…...
LeetCode 面试题 17.10. 主要元素
LeetCode 面试题 17.10. 主要元素 数组中占比超过一半的元素称之为主要元素。给你一个 整数 数组,找出其中的主要元素。若没有,返回 -1 。请设计时间复杂度为 O(N) 、空间复杂度为 O(1) 的解决方案。 示例 1: 输入:[1,2,5,9,5,9,5…...
Hive之import和export使用详解
在hive-0.8.0后引入了import/export命令。 Export命令可以导出一张表或分区的数据和元数据信息到一个输出位置,并且导出数据可以被移动到另一个hadoop集群或hive实例,并且可以通过import命令导入数据。 当导出一个分区表,原始数据可能在hdf…...
SpringBoot数据字典字段自动生成对应code和desc
效果:接口会返回orderType,但是这个orderType是枚举的类型(1,2,3,4),我想多返回一个orderTypeDesc给前端展示,这样前端就可以直接拿orderTypeDesc使用了。 1. 定义注解 …...
HTML——16.相对路径
<!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title></head><body><a href"../../fj1/fj2/c.html" target"_blank">链接到c</a><!--相对路径:-->…...
字——位级运算与有无符号数之间的比较
前言 本文整理和归纳《深入理解计算机系统》这本书的内容,但本文不会继续长篇大论地去将所有内容都总结,而是总结笔者认为容易遗忘或混淆或表述不清的内容。 字 首先字这个概念对于学习过《计算机体系结构》或《操作系统》的同学都不陌生,…...
Python爬虫教程——7个爬虫小案例(附源码)_爬虫实例
本文介绍了7个Python爬虫小案例,包括爬取豆瓣电影Top250、猫眼电影Top100、全国高校名单、中国天气网、当当网图书、糗事百科段子和新浪微博信息,帮助读者理解并实践Python爬虫基础知识。 包含编程资料、学习路线图、源代码、软件安装包等!【…...
‘Optional. get()‘ without ‘isPresent()‘ check
在Java中,Optional类被引入主要是为了解决NullPointerException的问题,它提供了一种更优雅的方式来处理可能为null的情况。Optional.get()方法用于获取Optional实例中包含的值,但如果Optional实例是空的(即没有值)&…...
015-spring-动态原理、AOP的xml和注解方式
强制使用cglib动态代理 spring-AOP的使用...
统计颜色Count Color(POJ2777)题解
有一个长度为L厘米板,L是一个正整数,所以我们可以把它均匀地划分成L个部分,分别从左到右编号为1,2……L,每一个部分长度都为1厘米。现在我们必须给每个部分涂色,一个部分一种颜色,要求完成以下两…...
Nginx 配置 SSL(HTTPS)详解
Nginx作为一款高性能的HTTP和反向代理服务器,自然支持SSL/TLS加密通信。本文将详细介绍如何在Nginx中配置SSL,实现HTTPS的访问。 随着互联网安全性的日益重要,HTTPS协议逐渐成为网站加密通信的标配。Nginx作为一款高性能的HTTP和反向代理服务…...
Day10补代码随想录 理论基础|232.用栈实现队列|225.用队列实现栈|20.有效的括号|1047.删除字符串中的所有相邻重复项
栈和队列理论基础 抽象认识 栈是先进后出(FIFO),队列是先进先出(LIFO) 队首(先进))队尾(后进)栈顶(后进)栈底(先进) 栈(Stack) 只在一端进行进出操作(只在一端进一端出)像个篮球框,取用篮球从一端进出。 /进栈 int a[1000];//足够大的栈空间 int top-1…...
pytorch基础之注解的使用--003
Title 1.学习目标2.定义3.使用步骤4.结果 1.学习目标 针对源码中出现一些注解的问题,这里专门写一篇文章进行讲解。包括如何自定义注解,以及注意事项,相信JAVA中很多朋友业写过,但是今天写的是Python哦。。。 2.定义 在 Python…...
2024-12-30-g++
title: 探秘 g:C 编程的得力编译器 date: ‘2024-12-30’ category: blog tags: gC 编程编译器技术代码生成与优化 sig: compiler archives: ‘2024-12’ author:way_back summary: g 作为专门用于 C 语言的编译器,在 C 开发领域占据关键地位。它凭借对…...
互联网十万个为什么之什么是微服务
微服务(Microservices)是一种软件架构设计模式,它将应用程序分解为小型、自治的服务单元,这些服务单元可以独立部署、扩展和维护,其中每一个服务单元也都是一个微服务。 基于微服务形成的软件架构风格称为微服务架构&…...
mysql子查询
子查询是嵌套在另一个 SELECT, INSERT, UPDATE, 或 DELETE查询的 SQL 查询。子查询可以在 WHERE 子句中、FROM 子句或 SELECT 列表中出现。 以下是一些使用 MySQL 子查询的常见示例: 1.在 WHERE 子句中使用子查询: SELECT * FROM Employees WHERE s…...
智能故障诊断和寿命预测期刊推荐
往期精彩内容: Python-凯斯西储大学(CWRU)轴承数据解读与分类处理 基于FFT CNN - BiGRU-Attention 时域、频域特征注意力融合的轴承故障识别模型-CSDN博客 基于FFT CNN - Transformer 时域、频域特征融合的轴承故障识别模型-CSDN博客 P…...
根据语言变化动态更新图片资源方案
根据语言变化动态更新图片资源方案 一、需求描述二、关于 Locale三、实现方案3.1 方案一(不可行)3.2 方案二(不可行)3.3 方案三 一、需求描述 Android 项目中引导页图片包含文字信息,由于应用是适配了三种语言&#x…...
Python世界:数据结构易错点小结
Python世界:数据结构易错点小结 总体list列表tuple元组Stringdict字典mapset 部分笔记汇总,持续刷新中。区别于其他笔记之处在于,主要记录易错点坑点。 总体 数据结构声明辨析 list []tuple () const listditc {} hashset res set(list) 数…...
Linux | Ubuntu零基础安装 nvm 管理nodejs
目录 介绍 项目地址 前置工具 安装 查看环境配置 更新环境变量 查看版本 查看 nodejs包 列表 安装nodejs 查看 nvm 状态 测试 nodejs 介绍 nvm是什么?你可以把它理解成 nodejs的管理软件,方便快速切换nodejs的版本,达到兼容状态 …...
flask后端开发(3):html模板渲染
目录 渲染模板html模板获取路由参数 gitcode地址: https://gitcode.com/qq_43920838/flask_project.git 渲染模板 这样就能够通过html文件来渲染前端,而不是通过return了 html模板获取路由参数...
HAL 库句柄
一、命名方式:句柄是h为首字母,后面接协议名称 比如:huart、hadc、hi2c等 二、句柄类型: 这里拿huart举例,它的类型是UART_HandleTypeDef 进去stm32f1xx_hal_uart.h之后发现句柄的结构定义有部分是灰色的 灰色的当U…...
53.最大子数组和
53.最大子数组和 思路:动态规划 dp[i]表示截止到i的最大连续子数组的和 dp[0]nums[0] dp[i]max(dp[i-1]nums[i],nums[i]) 代码: class Solution { public:int maxSubArray(vector<int>& nums) {vector<int> dp(nums.size());dp[0]…...