Java中的阻塞队列

Java线程池(ThreadPoolExecutor)原理分析与使用 在我们的开发中“池”的概念并不罕见,有数据库连接池、线程池、对象池、常量池等等。下面我们主要针对线程池来一步一步揭开线程池的面纱。使用线程池的好处1、降低资源消耗 可以重复利用已创建的线程降低线程创建和销毁造成的消耗。 2、提高响应速度 当任务到达时,任务可以不需要等到线程创建就能立即执行。 3、提高线程的可管理性 线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性 阅读详情



1. 什么是阻塞队列?

阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,消费者是从队列里拿元素的线程。阻塞队列就是生产者存放元素的容器,而消费者也只从容器里拿元素。

阻塞队列提供了四种处理方法:

方法\处理方式抛出异常返回特殊值一直阻塞超时退出
插入方法add(e)offer(e)put(e)offer(e,time,unit)
移除方法remove()poll()take()poll(time,unit)
检查方法element()peek()不可用不可用
  • 抛出异常:是指当阻塞队列满时候,再往队列里插入元素,会抛出IllegalStateException(“Queue full”)异常。当队列为空时,从队列里获取元素时会抛出NoSuchElementException异常 。
  • 返回特殊值:插入方法会返回是否成功,成功则返回true。移除方法,则是从队列里拿出一个元素,如果没有则返回null
  • 一直阻塞:当阻塞队列满时,如果生产者线程往队列里put元素,队列会一直阻塞生产者线程,直到拿到数据,或者响应中断退出。当队列空时,消费者线程试图从队列里take元素,队列也会阻塞消费者线程,直到队列可用。
  • 超时退出:当阻塞队列满时,队列会阻塞生产者线程一段时间,如果超过一定的时间,生产者线程就会退出。

2. Java里的阻塞队列

JDK7提供了7个阻塞队列。分别是

  • ArrayBlockingQueue :一个由数组结构组成的有界阻塞队列。
  • LinkedBlockingQueue :一个由链表结构组成的有界阻塞队列。
  • PriorityBlockingQueue :一个支持优先级排序的无界阻塞队列。
  • DelayQueue:一个使用优先级队列实现的无界阻塞队列。
  • SynchronousQueue:一个不存储元素的阻塞队列。
  • LinkedTransferQueue:一个由链表结构组成的无界阻塞队列。
  • LinkedBlockingDeque:一个由链表结构组成的双向阻塞队列。

ArrayBlockingQueue

ArrayBlockingQueue是一个用数组实现的有界阻塞队列。此队列按照先进先出(FIFO)的原则对元素进行排序。默认情况下不保证访问者公平的访问队列,所谓公平访问队列是指阻塞的所有生产者线程或消费者线程,当队列可用时,可以按照阻塞的先后顺序访问队列,即先阻塞的生产者线程,可以先往队列里插入元素,先阻塞的消费者线程,可以先从队列里获取元素。通常情况下为了保证公平性会降低吞吐量。我们可以使用以下代码创建一个公平的阻塞队列:

1ArrayBlockingQueue fairQueue = new  ArrayBlockingQueue(1000,true);

访问者的公平性是使用可重入锁实现的,代码如下:

1public ArrayBlockingQueue(int capacity, boolean fair) {
2        if (capacity <= 0)
3            throw new IllegalArgumentException();
4        this.items = new Object[capacity];
5        lock = new ReentrantLock(fair);
6        notEmpty = lock.newCondition();
7        notFull =  lock.newCondition();
8}

LinkedBlockingQueue

LinkedBlockingQueue是一个用链表实现的有界阻塞队列。此队列的默认和最大长度为Integer.MAX_VALUE。此队列按照先进先出的原则对元素进行排序。

PriorityBlockingQueue

PriorityBlockingQueue是一个支持优先级的无界队列。默认情况下元素采取自然顺序排列,也可以通过比较器comparator来指定元素的排序规则。元素按照升序排列。

DelayQueue

DelayQueue是一个支持延时获取元素的无界阻塞队列。队列使用PriorityQueue来实现。队列中的元素必须实现Delayed接口,在创建元素时可以指定多久才能从队列中获取当前元素。只有在延迟期满时才能从队列中提取元素。我们可以将DelayQueue运用在以下应用场景:

  • 缓存系统的设计:可以用DelayQueue保存缓存元素的有效期,使用一个线程循环查询DelayQueue,一旦能从DelayQueue中获取元素时,表示缓存有效期到了。
  • 定时任务调度。使用DelayQueue保存当天将会执行的任务和执行时间,一旦从DelayQueue中获取到任务就开始执行,从比如TimerQueue就是使用DelayQueue实现的。

队列中的Delayed必须实现compareTo来指定元素的顺序。比如让延时时间最长的放在队列的末尾。实现代码如下:

01public int compareTo(Delayed other) {
02           if (other == this) // compare zero ONLY if same object
03                return 0;
04            if (other instanceof ScheduledFutureTask) {
05                ScheduledFutureTask x = (ScheduledFutureTask)other;
06                long diff = time - x.time;
07                if (diff < 0)
08                    return -1;
09                else if (diff > 0)
10                    return 1;
11       else if (sequenceNumber < x.sequenceNumber)
12                    return -1;
13                else
14                    return 1;
15            }
16            long d = (getDelay(TimeUnit.NANOSECONDS) -
17                      other.getDelay(TimeUnit.NANOSECONDS));
18            return (d == 0) ? 0 : ((d < 0) ? -1 : 1);
19        }

如何实现Delayed接口

我们可以参考ScheduledThreadPoolExecutor里ScheduledFutureTask类。这个类实现了Delayed接口。首先:在对象创建的时候,使用time记录前对象什么时候可以使用,代码如下:

1ScheduledFutureTask(Runnable r, V result, long ns, long period) {
2            super(r, result);
3            this.time = ns;
4            this.period = period;
5            this.sequenceNumber = sequencer.getAndIncrement();
6}

然后使用getDelay可以查询当前元素还需要延时多久,代码如下:

public long getDelay(TimeUnit unit) {
            return unit.convert(time - now(), TimeUnit.NANOSECONDS);
        }

通过构造函数可以看出延迟时间参数ns的单位是纳秒,自己设计的时候最好使用纳秒,因为getDelay时可以指定任意单位,一旦以纳秒作为单位,而延时的时间又精确不到纳秒就麻烦了。使用时请注意当time小于当前时间时,getDelay会返回负数。

如何实现延时队列

延时队列的实现很简单,当消费者从队列里获取元素时,如果元素没有达到延时时间,就阻塞当前线程。

1long delay = first.getDelay(TimeUnit.NANOSECONDS);
2                    if (delay <= 0)
3                        return q.poll();
4                    else if (leader != null)
5                        available.await();

SynchronousQueue

SynchronousQueue是一个不存储元素的阻塞队列。每一个put操作必须等待一个take操作,否则不能继续添加元素。SynchronousQueue可以看成是一个传球手,负责把生产者线程处理的数据直接传递给消费者线程。队列本身并不存储任何元素,非常适合于传递性场景,比如在一个线程中使用的数据,传递给另外一个线程使用,SynchronousQueue的吞吐量高于LinkedBlockingQueue 和 ArrayBlockingQueue。

LinkedTransferQueue

LinkedTransferQueue是一个由链表结构组成的无界阻塞TransferQueue队列。相对于其他阻塞队列LinkedTransferQueue多了tryTransfer和transfer方法。

transfer方法。如果当前有消费者正在等待接收元素(消费者使用take()方法或带时间限制的poll()方法时),transfer方法可以把生产者传入的元素立刻transfer(传输)给消费者。如果没有消费者在等待接收元素,transfer方法会将元素存放在队列的tail节点,并等到该元素被消费者消费了才返回。transfer方法的关键代码如下:

1Node pred = tryAppend(s, haveData);
2return awaitMatch(s, pred, e, (how == TIMED), nanos);

第一行代码是试图把存放当前元素的s节点作为tail节点。第二行代码是让CPU自旋等待消费者消费元素。因为自旋会消耗CPU,所以自旋一定的次数后使用Thread.yield()方法来暂停当前正在执行的线程,并执行其他线程。

tryTransfer方法。则是用来试探下生产者传入的元素是否能直接传给消费者。如果没有消费者等待接收元素,则返回false。和transfer方法的区别是tryTransfer方法无论消费者是否接收,方法立即返回。而transfer方法是必须等到消费者消费了才返回。

对于带有时间限制的tryTransfer(E e, long timeout, TimeUnit unit)方法,则是试图把生产者传入的元素直接传给消费者,但是如果没有消费者消费该元素则等待指定的时间再返回,如果超时还没消费元素,则返回false,如果在超时时间内消费了元素,则返回true。

LinkedBlockingDeque

LinkedBlockingDeque是一个由链表结构组成的双向阻塞队列。所谓双向队列指的你可以从队列的两端插入和移出元素。双端队列因为多了一个操作队列的入口,在多线程同时入队时,也就减少了一半的竞争。相比其他的阻塞队列,LinkedBlockingDeque多了addFirst,addLast,offerFirst,offerLast,peekFirst,peekLast等方法,以First单词结尾的方法,表示插入,获取(peek)或移除双端队列的第一个元素。以Last单词结尾的方法,表示插入,获取或移除双端队列的最后一个元素。另外插入方法add等同于addLast,移除方法remove等效于removeFirst。但是take方法却等同于takeFirst,不知道是不是Jdk的bug,使用时还是用带有First和Last后缀的方法更清楚。在初始化LinkedBlockingDeque时可以初始化队列的容量,用来防止其再扩容时过渡膨胀。另外双向阻塞队列可以运用在“工作窃取”模式中。

3. 阻塞队列的实现原理

如果队列是空的,消费者会一直等待,当生产者添加元素时候,消费者是如何知道当前队列有元素的呢?如果让你来设计阻塞队列你会如何设计,让生产者和消费者能够高效率的进行通讯呢?让我们先来看看JDK是如何实现的。

使用通知模式实现。所谓通知模式,就是当生产者往满的队列里添加元素时会阻塞住生产者,当消费者消费了一个队列中的元素后,会通知生产者当前队列可用。通过查看JDK源码发现ArrayBlockingQueue使用了Condition来实现,代码如下:

01private final Condition notFull;
02private final Condition notEmpty;
03 
04public ArrayBlockingQueue(int capacity, boolean fair) {
05        //省略其他代码
06        notEmpty = lock.newCondition();
07        notFull =  lock.newCondition();
08    }
09 
10public void put(E e) throws InterruptedException {
11        checkNotNull(e);
12        final ReentrantLock lock = this.lock;
13        lock.lockInterruptibly();
14        try {
15            while (count == items.length)
16                notFull.await();
17            insert(e);
18        } finally {
19            lock.unlock();
20        }
21}
22 
23public E take() throws InterruptedException {
24        final ReentrantLock lock = this.lock;
25        lock.lockInterruptibly();
26        try {
27            while (count == 0)
28                notEmpty.await();
29            return extract();
30  } finally {
31            lock.unlock();
32        }
33}
34 
35private void insert(E x) {
36        items[putIndex] = x;
37        putIndex = inc(putIndex);
38        ++count;
39        notEmpty.signal();
40    }

当我们往队列里插入一个元素时,如果队列不可用,阻塞生产者主要通过LockSupport.park(this);来实现

01public final void await() throws InterruptedException {
02            if (Thread.interrupted())
03                throw new InterruptedException();
04            Node node = addConditionWaiter();
05            int savedState = fullyRelease(node);
06            int interruptMode = 0;
07            while (!isOnSyncQueue(node)) {
08                LockSupport.park(this);
09                if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
10                    break;
11            }
12            if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
13                interruptMode = REINTERRUPT;
14            if (node.nextWaiter != null) // clean up if cancelled
15                unlinkCancelledWaiters();
16            if (interruptMode != 0)
17 
18reportInterruptAfterWait(interruptMode);
19        }

继续进入源码,发现调用setBlocker先保存下将要阻塞的线程,然后调用unsafe.park阻塞当前线程。

1public static void park(Object blocker) {
2        Thread t = Thread.currentThread();
3        setBlocker(t, blocker);
4        unsafe.park(false, 0L);
5        setBlocker(t, null);
6    }

unsafe.park是个native方法,代码如下:

1public native void park(boolean isAbsolute, long time);

park这个方法会阻塞当前线程,只有以下四种情况中的一种发生时,该方法才会返回。

  • 与park对应的unpark执行或已经执行时。注意:已经执行是指unpark先执行,然后再执行的park。
  • 线程被中断时。
  • 如果参数中的time不是零,等待了指定的毫秒数时。
  • 发生异常现象时。这些异常事先无法确定。

我们继续看一下JVM是如何实现park方法的,park在不同的操作系统使用不同的方式实现,在linux下是使用的是系统方法pthread_cond_wait实现。实现代码在JVM源码路径src/os/linux/vm/os_linux.cpp里的 os::PlatformEvent::park方法,代码如下:

01void os::PlatformEvent::park() {
02             int v ;
03         for (;;) {
04        v = _Event ;
05         if (Atomic::cmpxchg (v-1, &_Event, v) == v) break ;
06         }
07         guarantee (v >= 0, "invariant") ;
08         if (v == 0) {
09         // Do this the hard way by blocking ...
10         int status = pthread_mutex_lock(_mutex);
11         assert_status(status == 0, status, "mutex_lock");
12         guarantee (_nParked == 0, "invariant") ;
13         ++ _nParked ;
14         while (_Event < 0) {
15         status = pthread_cond_wait(_cond, _mutex);
16         // for some reason, under 2.7 lwp_cond_wait() may return ETIME ...
17         // Treat this the same as if the wait was interrupted
18         if (status == ETIME) { status = EINTR; }
19         assert_status(status == 0 || status == EINTR, status, "cond_wait");
20         }
21         -- _nParked ;
22 
23         // In theory we could move the ST of 0 into _Event past the unlock(),
24         // but then we'd need a MEMBAR after the ST.
25         _Event = 0 ;
26         status = pthread_mutex_unlock(_mutex);
27         assert_status(status == 0, status, "mutex_unlock");
28         }
29         guarantee (_Event >= 0, "invariant") ;
30         }
31 
32     }

pthread_cond_wait是一个多线程的条件变量函数,cond是condition的缩写,字面意思可以理解为线程在等待一个条件发生,这个条件是一个全局变量。这个方法接收两个参数,一个共享变量_cond,一个互斥量_mutex。而unpark方法在linux下是使用pthread_cond_signal实现的。park 在windows下则是使用WaitForSingleObject实现的。

当队列满时,生产者往阻塞队列里插入一个元素,生产者线程会进入WAITING (parking)状态。我们可以使用jstack dump阻塞的生产者线程看到这点:

1"main" prio=5 tid=0x00007fc83c000000 nid=0x10164e000 waiting on condition [0x000000010164d000]
2   java.lang.Thread.State: WAITING (parking)
3        at sun.misc.Unsafe.park(Native Method)
4        - parking to wait for  <0x0000000140559fe8> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
5        at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186)
6        at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043)
7        at java.util.concurrent.ArrayBlockingQueue.put(ArrayBlockingQueue.java:324)
8        at blockingqueue.ArrayBlockingQueueTest.main(ArrayBlockingQueueTest.java:11)

4. 参考资料

源自: http://ifeve.com/java-blocking-queue/


Queue常用类解析之BlockingQueue(五):LinkedTransferQueue Queue常用类解析之PriorityQueue Queue常用类解析之ConcurrentLinkedQueue Queue常用类解析之BlockingQueue(一):PriorityBlockingQueue、DelayQueue和DelayedWorkQueue Queue常用类解析之BlockingQueue(二):ArrayBlockingQueue Queue常用类解析之Blocki... 阅读详情

相关推荐

【Java】阻塞队列

介绍阻塞队列的定义、种类、实现原理以及应用。

Creativity + Efficiency = Success 2031

阻塞队列详解

序言 由于最近项目上遇到了高并发问题,而自己对高并发,多线程这里的知识点相对薄弱,尤其是基础,所以想系统的学习一下,以后可能会出一系列的JUC文章及总结 ,同时也为企业级的高并发项目做好准备。 本文是JUC文章的第六篇,如想看以往关于JUC文章,请点击JUC系列总结 此系列文章的总结思路大致分为三部分: 理论(概念); 实践(代码证明); 总结(心得及适用场景)。 在这里提前说也是为了防止大家看着看着就迷路了。 备注:本文的知识深度相对较浅,可能仅局限于应用层面,如您需要相应足够的深度,请另行查阅。

罗伯特是疯子丶 1万+

【JAVA多线程19】JAVA 阻塞队列原理

今天我们来讨论另外一类容器:阻塞队列。   非阻塞队列,比如PriorityQueue、LinkedList(LinkedList是双向链表,它实现了Dequeue接口)。   使用非阻塞队列的时候有一个很大问题就是:它不会对当前线程产生阻塞,那么在面对类似消费者-生产者的模型时,就必须额外地实现同步策略以及线程间唤醒策略,这个实现起来就非常麻烦。但是有了阻塞队列就不一样了,它会对当前线程产生...

dcm19920115的博客 2067

阻塞队列(超详细易懂)

超详细大文,带你理解阻塞队列,以及和生产者消费者模型的关系,学会自己实现一个阻塞队列。阻塞队列是一种特殊的队列,同样遵循“先进先出”的原则,支持入队操作和出队操作。当队列已满时,继续入队列就会阻塞,直到有其他线程从队列中取走元素。当队列为空时,继续出队列也会阻塞,直到有其他线程向队列中插入元素。

a1302993809的博客 8124

Java面试——阻塞队列

阻塞队列 定义:顾名思义,首先它是一个队列,而一个阻塞队列在数据结构中所起的作用大致如下 当阻塞队列是空时,从队列中获取元素的操作会被阻塞。 当阻塞队列是满时,往队列里添加元素的操作将会被阻塞。 这个是消息队列的底层原理 优点:可以不用管阻塞或者唤醒,阻塞队列会解决,可以很简单的写出一个生产者消费者模式。 ...

清风丨的博客 1746

RT-Thread实战:手把手教你用STM32F04ZGT6通过SPI驱动BMI088(附完整工程)

本文详细介绍了如何使用RT-Thread操作系统在STM32F04ZGT6上通过SPI接口驱动BMI088高性能6轴惯性传感器(包含陀螺仪和加速度计)。从硬件连接到软件配置,再到数据采集与处理,提供了完整的开发指南和优化技巧,帮助开发者快速实现精确的姿态测量功能。

kappa的博客 236

聊聊并发-Java中的阻塞队列

转自:http://www.infoq.com/cn/articles/java-blocking-queue1. 什么是阻塞队列?阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会等待队列可用。阻塞队列常用于生产者和消费者的场景,生产者是往队列里添加元素的线程,...

weixin_33895695的博客 720

从零到一:嵌入式车载通信中间件VSOMEIP的跨平台构建之旅

本文详细介绍了嵌入式车载通信中间件VSOMEIP的跨平台构建过程,重点解析了交叉编译环境配置、Boost库编译、VSOMEIP定制化编译等关键技术环节。通过实战案例展示了在ARM架构嵌入式设备上的部署与调试方法,为开发者提供了一套完整的VSOMEIP嵌入式应用解决方案。

lilh34434的博客 195

JAVA中的阻塞队列

一.什么是阻塞队列?阻塞队列是一个在队列基础上又支持了两个附加操作的队列。2个附加操作: 支持阻塞的插入方法:队列满时,队列会阻塞插入元素的线程,直到队列不满。 支持阻塞的移除方法:队列空时,获取元素的线程会等待队列变为非空。 二.阻塞队列的应用场景阻塞队列常用于生产者和消费者的场景,生产者是向队列里添加元素的线程,消费者是从队列里取元素的线程。简而言之,阻塞队列是生产者用来存放元素、消费者获取元素

Fighting 6193

招财牛猫|股社区|猫笔刀公众号历史文章13-21年(含评论),投资内容 收藏学习

招财大牛猫|股社区|猫笔刀公主号历史文章13-21年(含评论)

ZhaoCaiDaNiuMao的博客 7230

百度地图街景图像批量获取

由于个人研究需要在最近试了一下使用API获取百度地图街景图片,在此介绍一下基于我个人需求的百度街景批量获取方法,本文以Python编码作为主要方法,如果对零编码工具有需要的可以关注一下UA城市分析小组刚刚发布的街景图片获取工具。 街景图像用作区域细粒度空间指标测度需要解决几个问题。 1. 首先就是调用额度的限制,现在百度对于个人认证开发者每天可用的街景图像调用额度为100张,在不考虑购买额度上限(1万张600元,其实有经费的前提下可以直接考虑钞能力)的情况下动辄几千上万张的爬取数量会大大增加需要爬取的时间周

boycetoon29的博客 1万+

java中的阻塞队列

Java中的阻塞队列 一、什么是阻塞队列 所谓的阻塞队列,指的是:如果当前队列为空,那么获取元素的线程就会被阻塞,处于等待状态,直到队列变为非空;如果当前队列满的时候,添加元素的线程就会被阻塞,处于等待状态,直到队列有存储空间。阻塞队列是一个经典的生产者-消费者模式,生产者不停的往队列里面添加元素,消费者不停的从队列消费元素。阻塞队列就是实现生产者-消费者模式借助的第三方,很多时候,我们找到这

牛奋lch 1209

YOLO26小目标检测实战:STAL标签分配+MuSGD优化,VisDrone数据集漏检率降50%

小目标检测是计算机视觉的经典难题,而VisDrone数据集小目标占比极高:数据集中小目标(像素面积<32×32)占比超过60%,且大量目标仅为几个像素,特征信息极度匮乏;背景复杂且干扰多:无人机航拍场景包含建筑物、树木、人群、车辆等复杂背景,小目标易被背景淹没;尺度变化与遮挡严重:同一目标在不同帧中尺度差异大,且小目标极易被其他目标遮挡;传统模型的固有缺陷标签分配策略(如ATSS、SimOTA)偏向大目标,小目标的正样本分配不足,导致模型对小目标不敏感;

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1183

Java多线程案例之阻塞队列

本篇文章将介绍Java多线程案例,阻塞队列,阻塞队列在普通队列的基础上多了两种情况,一是阻塞队列为空时,如果进行出队操作,会使当前线程阻塞,直到有新元素插入阻塞队列,该线程才被通知继续执行出队操作;二是阻塞队列为满时,如果进行入队操作,会使当前线程阻塞,直到有元素出队时,该线程才会被通知继续执行入队操作。在实际开发中,常常使用消息队列,而消息队列就是阻塞队列,只是在阻塞队列的基础上增加了很多功能。

未见花闻的博客 4917

【教程4>第1章>第12节】通过Verilog读取txt格式数据进行测试并将结果导入到matlab

我们在verilog的testbench中,调用txt文件,将上述正弦样本数据作为测试激励输入到verilog模块中。通过这个方法,可以将一些较为复杂的数据导入到verilog中,进行FPGA数据处理模块的开发。即通过w方式打开一个新的txt文件,然后将verilog的输出保存到XY1.txt文件中。这个部分是txt文件的路径,实际使用时,修改为您自己的路径,或者将txt文件放在和我一样的路径中。这个是数据长度,matlab产生的txt多少长度,这个参数就修改为多少长度。这个txt就是保存这段数据的文件。

FPGA/MATLAB学习教程/源码/项目合作开发 1374

电子图像增稳(EIS)原理详解——从抖动补偿到代码实现

电子图像增稳(EIS)是一种通过软件算法实现视频稳定的技术,广泛应用于GoPro、手机和无人机等设备。与光学防抖(OIS)和机械云台不同,EIS通过图像裁切和运动补偿来消除抖动,具有成本低、补偿范围大的优点,但会损失10-30%的画幅。其核心流程包括运动检测、抖动分离、运动补偿和图像裁切四个步骤。相比硬件方案,纯软件实现的EIS更适合消费级电子产品,已成为移动设备视频拍摄的重要技术。

电脑管家 409

Java阻塞队列

阻塞队列(Blocking Queue)是一种特殊的队列,因其为队列,因此遵循“先进先出”的原则,此外,其是一种线程安全的数据结构,具有以下两点特性:1. 当队列满时,继续入队列就会阻塞,直到有线程将元素从队列中取出2. 当队列空时,继续出队列就会阻塞,直到有线程向队列中插入元素阻塞队列常用于“生产者消费者模型什么是“生产者消费者模型”?“生产者消费者模式”是一种典型的开发模型,通过一个容器来解决生产者和消费者的强耦合问题向队列中添加元素的线程向队列中取出元素的线程。

2301_76161469的博客 2038

【100%通过率】华为od机试C卷【出差 / 员工派遣】Java&Go 实现

某公司部门需要派遣员工去国外做项目。现在,代号为 x 的国家和代号为 y 的国家分别需要 cntx 名和 cnty 名员工部门每个员工有一个员工号 (1,2,3,......),工号连续,从 1开始。部长派遣员工的规则:

MISAYAONE的博客 2637

JAVA阻塞队列

JAVA阻塞队列

Excuse_lighttime的博客 1674

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

Java阻塞队列原理

阻塞队列,关键字是阻塞,先理解阻塞的含义,阻塞队列中,线程阻塞有这样两种情况:当队列中没有数据的情况下,消费者端的所有线程都会被自动阻塞(挂起),直到有数据放入队列当队列中填满数据额情况下,生产者端的所有线程都会被自动阻塞(挂起),直到队列中有空的位置,线程被自动唤醒。

m0_73770897的博客 1591

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Java中的几种阻塞队列

提供四种不同的处理方法。| | 抛出异常 | 返回特殊值 | 一直阻塞 | 超时退出 || 插入方法 | add(o) | offer(o) | put(o) | offer(o, timeout, timeunit) || 移除方法 | remove(o) | poll() | take(o) | poll(o, timeout, timeunit) || 检查方法 | element() | peek() | — | — |add: 插入数据时,如果阻塞队列满,那么抛出异常。

2401_89758592的博客 1078

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

java之阻塞队列(BlockingQueue)

java之阻塞队列一、阻塞队列概念二、阻塞队列的好处三、阻塞队列种类四、BlockingQueue的核心方法五、示例代码1.使用SychronousQueue队列2.传统版生产者消费者模式3.阻塞队列版(以ArrayBlockingQueue为例)生产者消费者模式 一、阻塞队列概念 阻塞队列,顾名思义,首先它是一个队列(先进先出),而一个阻塞队列在数据结构所起到的作用大致如下图: 线程1往阻塞队列中添加元素,而线程2从阻塞队列中移除元素 当阻塞队列是空是,从队列中获取元素的操作会被阻塞 当阻塞队列是满时

weixin_43824267的博客 3006
上一篇: Java中的Copy-On-Write容器
下一篇: Java 类加载体系与ContextClassLoader
架构师的清醒
博客等级 码龄14年 291粉丝 397原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值