Java并发50:并发集合系列-基于独占锁实现的双向阻塞队列LinkedBlockingDeque

转载 2018年04月15日 13:58:53

[超级链接:Java并发学习系列-绪论]
[系列序章:Java并发43:并发集合系列-序章]


原文地址:http://ifeve.com/concurrent-collections-3/

关于与LinkedBlockingDeque类似的单向队列LinkedBlockingQueue可以参考:Java并发49

使用阻塞线程安全的列表

列表(list)是最基本的集合。

一个列表中的元素数量是不确定的,并且你可以添加、读取和删除任意位置上的元素。

并发列表允许不同的线程在同一时刻对列表里的元素进行添加或删除,而不会产生任何数据不一致的问题。

在这个指南中,你将学习如何在你的并发应用程序中使用阻塞的列表。

阻塞列表与非阻塞列表的主要区别是,阻塞列表有添加和删除元素的方法,如果由于列表已满或为空而导致这些操作不能立即进行,它们将阻塞调用的线程,直到这些操作可以进行。

Java包含实现阻塞列表的LinkedBlockingDeque类。

你将使用以下两种任务来实现例子:

  • 添加大量数据到列表。
  • 从同一个列表中删除大量的数据。

准备工作…

这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

如何做…

按以下步骤来实现的这个例子:

1.创建一个实现Runnable接口的Client类。

public class Client implements Runnable{

2.声明一个私有的、LinkedBlockingDeque类型的、参数化为String类的属性requestList。

private LinkedBlockingDeque requestList;

3.实现这个类的构造器,并初始化它的属性。

public Client (LinkedBlockingDeque requestList) {
    this.requestList=requestList;
}

4.实现run()方法。使用requestList对象的put()方法,每秒往列表插入5个String对象。重复这个循环3次。

@Override
public void run() {
    for (int i=0; i<3; i++) {
        for (int j=0; j<5; j++) {
            StringBuilder request=new StringBuilder();
            request.append(i);
            request.append(":");
            request.append(j);
            try {
                requestList.put(request.toString());
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("Client: %s at %s.\n",request,new Date());
        }
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    System.out.printf("Client: End.\n");
}

5.创建这个例子的主类,通过实现Main类,并实现main()方法。

public class Main {
public static void main(String[] args) throws Exception {

6.声明和创建参数化为String类、名为list的LinkedBlockingDeque。

LinkedBlockingDeque
list=new LinkedBlockingDeque(3);

7.创建和启动一个Thread对象来执行client任务。

Client client=new Client(list);
Thread thread=new Thread(client);
thread.start();

8.使用这个列表的take()方法,每300毫秒获取列表的3个字符串(String)对象。重复这个循环5次。将字符串(String)写入到控制台。

for (int i=0; ifor (int j=0; j<3; j++) {
    String request=list.take();
    System.out.printf("Main: Request: %s at %s. Size:%d\n",request,new Date(),list.size());
}
TimeUnit.MILLISECONDS.sleep(300);

9.写入一条信息表明程序的结束。

System.out.printf("Main: End of the program.\n");

它是如何工作的…

在这个指南中,你已使用参数化为String类的LinkedBlockingDeque来处理非阻塞并发列表的数据。

Client类使用put()方法添加字符串到列表中。如果列表已满(因为你已使用固定大小来创建它),这个方法阻塞线程的执行,直到列表有可用空间。

Main类使用take()方法从列表中获取字符串,如果列表为空,这个方法将阻塞线程的执行,直到列表中有元素。

在这个例子中,使用LinkedBlockingDeque类的这两个方法,如果它们在阻塞时被中断,将抛出InterruptedException异常。所以,你必须包含必要的代码来捕捉这个异常。

不止这些…

LinkedBlockingDeque类同时提供方法用于添加和获取列表的元素,而不被阻塞,或抛出异常,或返回null值。这些方法是:

  • takeFirst() 和takeLast():这些方法分别返回列表的第一个和最后一个元素。它们从列表删除返回的元素。如果列表为空,这些方法将阻塞线程,直到列表有元素。
  • getFirst() 和getLast():这些方法分别返回列表的第一个和最后一个元素。它们不会从列表删除返回的元素。如果列表为空,这些方法将抛出NoSuchElementExcpetion异常。
  • peek()、peekFirst(),和peekLast():这些方法分别返回列表的第一个和最后一个元素。它们不会从列表删除返回的元素。如果列表为空,这些方法将返回null值。
  • poll()、pollFirst()和 pollLast():这些方法分别返回列表的第一个和最后一个元素。它们从列表删除返回的元素。如果列表为空,这些方法将返回null值。
  • add()、 addFirst()、addLast():这些方法分别在第一个位置和最后一个位置上添加元素。如果列表已满(你已使用固定大小创建它),这些方法将抛出IllegalStateException异常。

Java并发包:双端阻塞队列(BlockingDeque)

BlockingDequeJava.util.concruuent包中的BlockingDeque接口是一种双端队列,向其中加入元素或从中取出元素都是线程安全的。这里展示如何使用BlockingDeq...
  • zxc123e
  • zxc123e
  • 2016-07-06 17:35:25
  • 6635

并发 加锁 以及Java api自身的阻塞队列

Java里的阻塞队列 阻塞队列(BlockingQueue)是一个支持两个附加操作的队列。这两个附加的操作是:在队列为空时,获取元素的线程会等待队列变为非空。当队列满时,存储元素的线程会...
  • zhuangyalei
  • zhuangyalei
  • 2015-09-21 16:50:15
  • 2022

java并发系列——并发集合(一)

在编程语言中,数据结构是一种能为计算机提供数据存储的元素,在java语言中,提供了集合框架,实现不同类型的数据结构的属性,类和接口等,可以应用于程序中。 在并发编程中,常用的大多数集合并不适用,因为...
  • xhwwc110
  • xhwwc110
  • 2016-01-18 00:31:19
  • 1232

Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析(还没看,先马)

转自:Java阻塞队列ArrayBlockingQueue和LinkedBlockingQueue实现原理分析Java中的阻塞队列接口BlockingQueue继承自Queue接口。BlockingQ...
  • x_i_y_u_e
  • x_i_y_u_e
  • 2016-09-12 14:16:31
  • 2643

java中并发集合

在 Java 编程的早期阶段,位于 Oswego 市的纽约州立大学(SUNY) 的一位教授决定创建一个简单的库,以帮助开发人员构建可以更好地处理多线程情况的应用程序。这并不是说用现有的库就不能实现,但...
  • qq_14926159
  • qq_14926159
  • 2016-05-08 12:44:16
  • 2065

多线程访问共享锁和独占锁

SRWLOCK     g_sCallNumberMapRwLock;
  • liuyinghui523
  • liuyinghui523
  • 2014-10-22 10:51:45
  • 451

Java并发框架——AQS阻塞队列管理(一)——自旋锁

我们知道一个线程在尝试获取锁失败后将被阻塞并加入等待队列中,它是一个怎样的队列?又是如何管理此队列?这节聊聊CHL Node FIFO队列。  在谈到CHL Node FIFO队列之前,我们先分析这种...
  • wangyangzhizhou
  • wangyangzhizhou
  • 2014-12-20 22:58:45
  • 3565

【Java并发编程】阻塞队列(五)

我是小毛驴,一个游戏人,我的梦想是世界和平。转载请注明出处:http://blog.csdn.net/liulongling/article/details/50593326  一、什么是阻...
  • liulongling
  • liulongling
  • 2016-01-27 12:15:17
  • 2177

JAVA多线程(五)用lock、synchronized、阻塞队列三种方法实现生产者消费者模式

用乐观锁、悲观锁、阻塞队列三种方法实现生产者消费者模式
  • antony9118
  • antony9118
  • 2016-05-25 17:35:30
  • 2936
收藏助手
不良信息举报
您举报文章:Java并发50:并发集合系列-基于独占锁实现的双向阻塞队列LinkedBlockingDeque
举报原因:
原因补充:

(最多只允许输入30个字)