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

news/2024/7/3 15:04:05

[超级链接: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异常。

http://www.niftyadmin.cn/n/2815554.html

相关文章

hibernatenbsp;注解配置一对多关系

从Hibernate 2.5开始就可以使用annotation实现实体关系的映射了&#xff0c;减少了配置hbm文件的繁琐&#xff0c;而且annotation也是一种趋势&#xff0c;现在的SSH2的整合都是完全可以用annotation来实现。在以前实现一对多关联的关联式都是使用hbm文件&#xff0c;今天我们来…

React 作为一个 UI 运行时(一、宿主环境和渲染器)

很多教程把React介绍为一个UI框架。这很合理因为它就是一个UI库&#xff0c;这就是react标语的意思。这篇文章不会叫你任何关于建立用户界面的知识&#xff0c;但是会帮助你更生层次的理解React编程模型。这是一篇深入解析的文章&#xff0c;对初学者不太适合。在这篇文章我将通…

Java并发51:并发集合系列-基于独占锁+数组实现的单向阻塞有界队列ArrayBlockingQueue

[超级链接&#xff1a;Java并发学习系列-绪论] [系列序章&#xff1a;Java并发43:并发集合系列-序章] 原文地址&#xff1a;http://www.importnew.com/25566.html 一、 前言 上节介绍了无界链表方式的阻塞队列LinkedBlockingQueue&#xff0c;本节来研究下有界使用数组方式实…

lingo错误代码对照大全

需要lingo11破解版&#xff0c;请留下邮箱。 0 LINGO模型生成器的内存已经用尽(可用“LINGO|Options"命令对General Solver 选项卡中的“Generator Memory Limit"选项进行内存大小的修改) 1 模型中的行数太多(对于有实际意义的模型&#xff0c;这个错…

Java并发52:并发集合系列-基于独占锁+二叉树最小堆实现的单向阻塞无界优先级队列PriorityBlockingQueue

[超级链接&#xff1a;Java并发学习系列-绪论] [系列序章&#xff1a;Java并发43:并发集合系列-序章] 原文地址&#xff1a;http://www.importnew.com/25541.html 一、 前言 PriorityBlockingQueue是带优先级的无界阻塞队列&#xff0c;每次出队都返回优先级最高的元素&…

Mysql之Centos6.5+Mysql5.6搭建配置

下载mysql-xxx.tar.gz文件 将下载的文件通过ftp软件传到linux下/usr/local 解压并重命名 cd /usr/local tar -zxvf mysql-xxx.tar.gz mv mysql-xxx mysql 检测是否安装过mysql rpm -qa |grep mysql 删除旧版本mysql rpm -e mysql-server rpm -e mysql -nodeps 强制性 添加组和用…

oraclenbsp;表复制

1. 复制表结构及其数据&#xff1a;create table table_name_new as select * from table_name_old ;2. 只复制表结构&#xff1a;create table table_name_new as select * from table_name_old where 12;ORcreate table table_name_new like table_name_old ;3. 只复制表数据…

SparkSQL:使用反射、编程方式将RDD转换为DataFrame

为什么要将RDD转换为DataFrame&#xff1f;因为这样的话&#xff0c;我们就可以直接针对HDFS等任何可以构建为RDD的数据&#xff0c;使用Spark SQL进行SQL查询了。这个功能是无比强大的。想象一下&#xff0c;针对HDFS中的数据&#xff0c;直接就可以使用SQL进行查询。 一、Spa…