聊聊Java里常用的并发集合
前言
在我们的程序开发过程中,如果涉及到多线程环境,那么对于集合框架的使用就必须更加谨慎了,因为大部分的集合类在不施加额外控制的情况下直接在并发环境中直接使用可能会出现数据不一致的问题,所以为了解决这个潜在的问题,我们要么在自己的业务逻辑中加上一些额外的控制,例如锁,或者我们直接使用Java提供的可在并发环境中使用的集合类,这是一个简便而且高效的方法。那么我们下面就来了解下Java提供了哪些“神器”可以让我们安全的使用集合。
正文
非阻塞式安全列表 - ConcurrentLinkedDeque
ConcurrentLinkedDeque可以在并发环境中直接使用,所谓的非阻塞,就是当列表为空的时候,我们还继续从列表中取数据的话,它会直接返回null或者抛出异常。下面列出来一些常用的方法。
peekFirst()、peekLast():返回列表中首位跟末尾元素,如果列表为空则返回null。返回的元素不从列表中删除。getFirst()、getLast():返回列表中首位跟末尾元素,如果列表为空则抛出NoSuchElementExceotion异常。返回的元素不从列表中删除。removeFirst()、removeLast():返回列表中首位跟末尾元素,如果列表为空则抛出NoSuchElementExceotion异常。【返回的元素会从列表中删除】。
阻塞式安全列表 - LinkedBlockingDeque
LinkedBlockingDeque是一个阻塞式的线程安全列表,它跟 ConcurrentLinkedDeque最大的区别就是,当列表中元素满了或者为空的时候,我们对该列表的操作不会立即返回,而是阻塞当前操作,直到该操作可以执行时才返回。我们对比着上面ConcurrentLinkedDeque的常用方法,来看下LinkedBlockingDeque会有哪些不一致的地方呢?
put():插入元素至列表中,当表中元素已满的时候,该操作将会被阻塞,直到表中存在空余空间。take(): 从列表中获取元素,当列表为空,该操作会被阻塞,直到列表不为空。peekFirst()、peekLast():返回列表中首位跟末尾元素,如果列表为空则返回null。返回的元素不从列表中删除。getFirst()、getLast():返回列表中首位跟末尾元素,如果列表为空则抛出NoSuchElementExceotion异常。返回的元素不从列表中删除。addFirst()、addLast():将元素添加至首位跟末尾,如果列表已满,则会抛出IllegalStateException
可以看出不管是从获取还是插入元素,都多了不少“花样”,其差别就在于是否阻塞,不满足条件是否返回null,不满足条件是否抛异常这几个方面来区分。
优先级排序阻塞式安全列表 - PriorityBlockingQueue
相信大家都写过把某个列表元素按照特定的规则来排序之类的代码,在PriorityBlockingQueue中,存放进去的元素必须要实现Comparable接口。在这个接口中,有一个compareTo()方法,当执行该方法的对象跟参数传入的对象进行比较的时候,这个方法会返回一个数字值,如果值小于0,则当前对象小于参数传入对象。大于0则相反,等于0就表示两个对象相等。
public class DemoObj implements Comparable<DemoObj> {
private int priority;
@Override
public int compareTo(DemoObj do){
if(this.getPriority() > do.getPriority()){
return -1;
}else if(this.getPriority() < do.getPriority()){
return 1;
}
return 0;
}
//省略getset ...
}
//==== use ===================
PriorityBlockingQueue<DemoObj> queue = new PriorityBlockingQueue()<>;
queue.put(DemoObj);
queue.peek();
其常用方法跟上面提到的类基本都差不多大家可以动手实现一下,简单对比的话,可以说是LinkedBlockingDeque的增强版,多了元素排序功能。
延迟元素线程安全列表 - DelayQueue
DelayQueue 里面存放着带有日期的元素,当我们从列表获取数据的时候,未到时间的元素将会被忽略。因此,存放进来的元素必须实现Delayed接口,使之成为一个延迟对象。
/**
* compareTo方法与getDelay方法需排序一致
*/
class Order implements Delayed{ private String name ;
private long start = System.currentTimeMillis();
private long time ; public MyDelayedTask(String name,long time) {
this.name = name;
this.time = time;
} /**
* 需要实现的接口,获得延迟时间 用过期时间-当前时间
* @param unit
* @return
*/
@Override
public long getDelay(TimeUnit unit) {
return unit.convert((start+time) - System.currentTimeMillis(),TimeUnit.MILLISECONDS);
} /**
* 延迟队列内部排序 当前对象延迟时间 - 入参对象的延迟时间
* @param o
* @return
*/
@Override
public int compareTo(Delayed o) {
Order o1 = (Order) o;
return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o1.getDelay(TimeUnit.MILLISECONDS));
}
}
使用方式如下
private static DelayQueue delayQueue = new DelayQueue();
public static void main(String[] args) throws InterruptedException { new Thread(new Runnable() {
@Override
public void run() { delayQueue.offer(new Order("t3000",3000));
delayQueue.offer(new Order("t4000",4000));
delayQueue.offer(new Order("t2000",2000));
delayQueue.offer(new Order("t6000",6000));
delayQueue.offer(new Order("t1000",1000)); }
}).start(); while (true) {
Delayed take = delayQueue.take();
}
}
关于结果的输出大家可以动手尝试一下~
结语
这里仅仅是介绍了几种常用的并发集合,其目的主要是让大家对这些集合有一个直观的认识,在使用的时候可以思考下自己的场景用哪种更合适,如果当前介绍的类没合适的,那么是否还有其他并发集合会更有用呢?这里就当做抛砖引玉吧,有兴趣的朋友可以多去了解一下相关技术,相信你会有不少收获的。
公众号博文同步Github仓库,有兴趣的朋友可以帮忙给个Star哦,码字不易,感谢支持。
https://github.com/PeppaLittlePig/blog-wechat
推荐阅读
《如何优化代码中大量的if/else,switch/case?》
有收获的话,就点个赞吧
关注「深夜里的程序猿」,分享最干的干货
聊聊Java里常用的并发集合的更多相关文章
- java 多线程 同步 观察者 并发集合的一个例子
//第一版 package com.hra.riskprice; import com.hra.riskprice.SysEnum.Factor_Type; import org.springfram ...
- 【java】聊聊java里的接口
接口的概念 java中的接口用于描述类应该具备什么样的功能,而不给出具体的实现,一个类可以“实现”多个接口 [注意]接口不是类,而是对类的一组描述 还是让我们通过一个例子来看看接口如何运作吧! ...
- java中常用的并发工具类
· 1. 等待多线程完成的CountDownLatch 构造函数接收一个int类型的参数作为计数器,如果想等待N个点,就传入N.当调用CountDownLatch的countDown方法时,N就会减一 ...
- java里常用的redis客户端简介
Redis的各种语言客户端列表,请参见Redis Client.其中Java客户端在github上start最高的是Jedis和Redisson.Jedis提供了完整Redis命令,而Redisson ...
- Redis(六):java里常用的redis客户端(Jedis和Redisson)
Redis的各种语言客户端列表,请参见Redis Client.其中Java客户端在github上start最高的是Jedis和Redisson.Jedis提供了完整Redis命令,而Redisson ...
- 【Java】常用数据类型转换(BigDecimal、包装类、日期等)
新工作转到大数据方向,每天都要面对数据类型互相转换的工作,再加上先前面试发现这部分的知识盲点, 决定复习之余自己再写一套便捷的方法,以后会比较方便.(虽然公司有现成封装的类,里头还有些遗漏的地方,暂时 ...
- JAVA常用知识点总结---集合篇
一.Collection 与 Collections的区别:1. Collections:java.util.Collections 是一个包装类.它包含有各种有关集合操作的静态多态方法.此类不能实例 ...
- java多线程中并发集合和同步集合有哪些?区别是什么?
java多线程中并发集合和同步集合有哪些? hashmap 是非同步的,故在多线程中是线程不安全的,不过也可以使用 同步类来进行包装: 包装类Collections.synchronizedMap() ...
- Java多线程之同步集合和并发集合
Java多线程之同步集合和并发集合 不管是同步集合还是并发集合他们都支持线程安全,他们之间主要的区别体现在性能和可扩展性,还有他们如何实现的线程安全. 同步集合类 Hashtable Vector 同 ...
随机推荐
- MongoDB之增删改查(一)
本文主要介绍MongoDB数据库增删改查操作. 增 mongoDB和其它关系型数据库一样,通过insert来添加数据到集合中去. db.collectionName.insert(内容) 显示数据库中 ...
- [Python爬虫] Selenium自己主动訪问Firefox和Chrome并实现搜索截图
前两篇文章介绍了安装.此篇文章算是一个简单的进阶应用吧.它是在Windows下通过Selenium+Python实现自己主动訪问Firefox和Chrome并实现搜索截图的功能. [Python爬虫] ...
- 基于live555实现的跨平台高性能RTSPServer流媒体服务器EasyIPCamera
本文转自EasyDarwin团队成员kim的博客:http://blog.csdn.net/jinlong0603/article/details/52366412 简介 EasyIPCamera是由 ...
- java关于数组之间的相互赋值
java中数组是被当作对象看待,假设a,b为两个已经初始化的数组,那么语句a=b就表示把b数组对象的引用赋值给a,那么a和b就指向了同一个数组,无论用哪个来操作都影响其指向的数组.原来a指向的数组现在 ...
- 九度OJ 1106:数字之和 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2505 解决:1706 题目描述: 对于给定的正整数 n,计算其十进制形式下所有位置数字之和,并计算其平方的各位数字之和. 输入: 每行输入 ...
- Hackerspace
Hackerspace Software - HackerspaceWiki https://wiki.hackerspaces.org/Hackerspace_Software Hackerspac ...
- 【LeetCode】Sqrt(x) (转载)
Implement int sqrt(int x). Compute and return the square root of x. 原文地址: http://kb.cnblogs.com/page ...
- 在iOS平台使用ffmpeg解码h264视频流(转)
在iOS平台使用ffmpeg解码h264视频流,有需要的朋友可以参考下. 对于视频文件和rtsp之类的主流视频传输协议,ffmpeg提供avformat_open_input接口,直接将文件路径或UR ...
- (linux)BSP板级支持包开发理解
1. 概述 嵌入式系统由硬件环境.嵌入式操作系统和应用程序组成,硬件环境是操作系统和应用程序运行的硬件平台,它随应用的不同而有不同的要求.硬件平台的多样性是嵌入式系统的主要特点,如何使嵌入式操作系统在 ...
- input表单元素的默认padding不一致问题
最近做的项目,发现一堆问题,input type=“text”和type=“button” (1)在无文字的时候高度是一致的,分别写入相同大小的文字type=“button”高度>type=“t ...