阻塞队列

阻塞队列是Java 5并发新特性中的内容,阻塞队列的接口是java.util.concurrent.BlockingQueue,它有多个实现类:ArrayBlockingQueue、DelayQueue、LinkedBlockingQueue、PriorityBlockingQueue、SynchronousQueue等,用法大同小异,具体可查看JDK文档,这里简单举例看下ArrayBlockingQueue,它实现了一个有界队列,当队列满时,便会阻塞等待,直到有元素出队,后续的元素才可以被加入队列。

看下面的例子:

    import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue; public class BlockingQueueTest{
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> bqueue = new ArrayBlockingQueue<String>(20);
for (int i = 0; i < 30; i++) {
//将指定元素添加到此队列中
bqueue.put("加入元素" + i);
System.out.println("向阻塞队列中添加了元素:" + i);
}
System.out.println("程序到此运行结束,即将退出----");
}
}

输出结果如下:

从执行结果中可以看出,由于队列中元素的数量限制在了20个,因此添加20个元素后,其他元素便在队列外阻塞等待,程序并没有终止。

如果队列已满后,我们将队首元素移出,并可以继续向阻塞队列中添加元素,修改代码如下:

    import java.util.concurrent.BlockingQueue;
import java.util.concurrent.ArrayBlockingQueue; public class BlockingQueueTest{
public static void main(String[] args) throws InterruptedException {
BlockingQueue<String> bqueue = new ArrayBlockingQueue<String>(20);
for (int i = 0; i < 30; i++) {
//将指定元素添加到此队列中
bqueue.put("" + i);
System.out.println("向阻塞队列中添加了元素:" + i);
if(i > 18){
//从队列中获取队头元素,并将其移出队列
System.out.println("从阻塞队列中移除元素:" + bqueue.take());
}
}
System.out.println("程序到此运行结束,即将退出----");
}
}

执行结果如下:

从结果中可以看出,当添加了第20个元素后,我们从队首移出一个元素,这样便可以继续向队列中添加元素,之后每添加一个元素,便从将队首元素移除,这样程序便可以执行结束。

阻塞栈

阻塞栈与阻塞队列相似,只是它是Java 6中加入的新特性,阻塞栈的接口java.util.concurrent.BlockingDeque也有很多实现类,使用方法也比较相似,具体查看JDK文档。

下面同样给出一个简单的例子:

    import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque; public class BlockingDequeTest {
public static void main(String[] args) throws InterruptedException {
BlockingDeque<String> bDeque = new LinkedBlockingDeque<String>(20);
for (int i = 0; i < 30; i++) {
//将指定元素添加到此阻塞栈中
bDeque.putFirst("" + i);
System.out.println("向阻塞栈中添加了元素:" + i);
}
System.out.println("程序到此运行结束,即将退出----");
}
}

执行结果如下:

程序依然会阻塞等待,我们改为如下代码:

    import java.util.concurrent.BlockingDeque;
import java.util.concurrent.LinkedBlockingDeque; public class BlockingDequeTest {
public static void main(String[] args) throws InterruptedException {
BlockingDeque<String> bDeque = new LinkedBlockingDeque<String>(20);
for (int i = 0; i < 30; i++) {
//将指定元素添加到此阻塞栈中
bDeque.putFirst("" + i);
System.out.println("向阻塞栈中添加了元素:" + i);
if(i > 18){
//从阻塞栈中取出栈顶元素,并将其移出
System.out.println("从阻塞栈中移出了元素:" + bDeque.pollFirst());
}
}
System.out.println("程序到此运行结束,即将退出----");
}
}

执行结果如下:

    从结果中可以看出,当添加了第20个元素后,我们从将栈顶元素移处,这样便可以继续向栈中添加元素,之后每添加一个元素,便将栈顶元素移出,这样程序便可以执行结束。

java并发编程(十八)阻塞队列和阻塞栈的更多相关文章

  1. Java并发(十八):阻塞队列BlockingQueue

    阻塞队列(BlockingQueue)是一个支持两个附加操作的队列. 这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空.当队列满时,存储元素的线程会等待队列可用. 阻塞队列常用于生产 ...

  2. 【Java并发编程实战】----- AQS(三):阻塞、唤醒:LockSupport

    在上篇博客([Java并发编程实战]----- AQS(二):获取锁.释放锁)中提到,当一个线程加入到CLH队列中时,如果不是头节点是需要判断该节点是否需要挂起:在释放锁后,需要唤醒该线程的继任节点 ...

  3. Java并发编程实战.笔记十一(非阻塞同步机制)

    关于非阻塞算法CAS. 比较并交换CAS:CAS包含了3个操作数---需要读写的内存位置V,进行比较的值A和拟写入的新值B.当且仅当V的值等于A时,CAS才会通过原子的方式用新值B来更新V的值,否则不 ...

  4. Java并发编程(八)同步容器

    为了方便编写出线程安全的程序,Java里面提供了一些线程安全类和并发工具,比如:同步容器.并发容器.阻塞队列.Synchronizer(比如CountDownLatch) 一.为什么会出现同步容器? ...

  5. Java并发编程 (十) 多线程并发拓展

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 一.死锁 1.死锁的定义 所谓的死锁是指两个或两个以上的线程在等待执行的过程中,因为竞争资源而造成的一种 ...

  6. Java并发编程(八)线程间协作(上)

    多线程并发执行时,不同的线程执行的内容之间可能存在一些依赖关系,比如线程一执行a()方法和c()方法,线程二执行b()方法,方法a()必须在方法b()之前执行,而方法c()必须在方法b()之后执行.这 ...

  7. Java并发编程3-抽象同步队列AQS详解

    AQS是AtractQueuedSynchronizer(队列同步器)的简写,是用来构建锁或其他同步组件的基础框架.主要通过一个int类型的state来表示同步状态,内部有一个FIFO的同步队列来实现 ...

  8. java并发编程(八)多线程环境下安全使用集合

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17200509     在集合API中,最初设计的Vector和Hashtable是多线程安 ...

  9. Java并发编程(八)-- 死锁

    简介 当两个以上的运算单元,双方都在等待对方停止运行,以获取系统资源,但是没有一方提前退出时,就称为死锁.在多任务操作系统中,操作系统为了协调不同进程,能否获取系统资源时,为了让系统运作,必须要解决这 ...

  10. Java并发编程(八):线程调度——线程池

    new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { / ...

随机推荐

  1. VC++ : error LNK2005: ... already defined in *.obj

    今天写代码遇到了这么一个链接错误:"已经在*.obj中定义". error LNK2005: "void __cdecl ReplaceWstringVar(class ...

  2. Ubuntu16.04 VTK7.1.0+QT4.8.6+QtCreator开发环境配置

    VTK需要OpenGL3.0或更高版本的驱动,但虚拟机下的Ubuntu不支持OpenGL3.0,或者自己按网上教程配置之后也能支持,但过程相当繁琐,本人试验失败. 最终决心采用双系统,装好之后,执行g ...

  3. qt5.5程序打包发布以及依赖【转】

    玩qt5也有一段时间了,惭愧的是一直没有好好的发布过程序,因为写的都是小程序没啥需要用到发布,而且qt也说不上很熟悉,本来打算到基本掌握qt之后再来研究研究怎么打包程序,最近晚上的空闲时间多了,闲着也 ...

  4. Qt5.5.1编译出来的程序出现libgcc_s_dw2-1.dll的解决方案

    问题如图: 输入"myudp2016.exe 1  " 后出现 这是因为没有在系统环境变量path里加上相关路径,我们添加如下路径: 比如说WIN7系统-开始-计算机-右键-属性- ...

  5. 非旋treap模板

    bzoj3580 非旋转treap 在大神教导下发现split一段区间时先split右边再split左边比较好写 #include <cstdio> #include <cstdli ...

  6. Ext.js的store里放model,还是field?

    按别人的经验, 一般来说,如果通用性强的应用,STORE里存放MODEL,便于重用代码. 如果通用性较弱的(报告,图表),则考虑使用field进行定制.

  7. HDU 5742 Chess SG函数博弈

    Chess Problem Description   Alice and Bob are playing a special chess game on an n × 20 chessboard. ...

  8. Redis设置认证密码 Redis使用认证密码登录 在Redis集群中使用认证密码

    Redis默认配置是不需要密码认证的,也就是说只要连接的Redis服务器的host和port正确,就可以连接使用.这在安全性上会有一定的问题,所以需要启用Redis的认证密码,增加Redis服务器的安 ...

  9. 解决谷歌浏览器中的input背景色默认是黄色

    input:-webkit-autofill { -webkit-box-shadow: 0 0 0px 1000px white inset !important; }

  10. Jstack Jmap jstat

    jstack jmap jstat 代码,这里以这个为例怎样使用jstack诊断Java应用程序故障 public class DeadLock { public static void main(S ...