非阻塞线程安全列表——ConcurrentLinkedDeque应用举例
发布日期:2021-07-01 01:39:32
浏览次数:2
分类:技术文章
本文共 4004 字,大约阅读时间需要 13 分钟。
转载自
在java中,最常用的数据结构可能是列表。有数目不详的元素列表,你可以添加、阅读、或删除任何位置的元素。此外,并发列表允许不同的线程列表中添加或删除元素时不产生任何数据不一致。非阻塞列表提供如下操作,如果操作不能立即完成,列出抛出异常或者返回一个null值。Java 7中引入了ConcurrentLinkedDeque类,它实现了一个非阻塞并发列表,在本教程中,我们将学习使用这个类。
在这个例子中,我们将实现一个示例使用以下两个不同的任务:
一个将大量数据添加到一个列表中
一个大量地从同样的列表中删除数据 让我们为每个任务创建的线程:package com.howtodoinjava.demo.multithreading.concurrentLinkedDequeExample; import java.util.concurrent.ConcurrentLinkedDeque; public class AddTask implements Runnable { private ConcurrentLinkedDequelist; public AddTask(ConcurrentLinkedDeque list) { this.list = list; } @Override public void run() { String name = Thread.currentThread().getName(); for (int i = 0; i < 10000; i++) { list.add(name + ": Element " + i); } } }
和:
packagecom.howtodoinjava.demo.multithreading.concurrentLinkedDequeExample; importjava.util.concurrent.ConcurrentLinkedDeque; publicclass RemoveTask implementsRunnable { privateConcurrentLinkedDequelist; publicRemoveTask(ConcurrentLinkedDeque list) { this.list = list; } @Override publicvoid run() { for(inti = 0; i < 5000; i++) { list.pollFirst(); list.pollLast(); } }}
现在,让我们创建100个线程将数据添加到列表和100个线程从列表删除数据。如果真的是线程安全的和非阻塞,它会几乎立即给你最终结果。此外,列表大小最终将是零。
package com.howtodoinjava.demo.multithreading.concurrentLinkedDequeExample; import java.util.concurrent.ConcurrentLinkedDeque; public class Main { public static void main(String[] args) { ConcurrentLinkedDequelist = new ConcurrentLinkedDeque<>(); Thread threads[] = new Thread[100]; for (int i = 0; i < threads.length; i++) { AddTask task = new AddTask(list); threads[i] = new Thread(task); threads[i].start(); } System.out.printf("Main: %d AddTask threads have been launched\n", threads.length); for (int i = 0; i < threads.length; i++) { try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("Main: Size of the List: %d\n", list.size()); for (int i = 0; i < threads.length; i++) { RemoveTask task = new RemoveTask(list); threads[i] = new Thread(task); threads[i].start(); } System.out.printf("Main: %d RemoveTask threads have been launched\n", threads.length); for (int i = 0; i < threads.length; i++) { try { threads[i].join(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.printf("Main: Size of the List: %d\n", list.size()); } }
Output:
Main: 100 AddTask threads have been launched Main: Size of the List: 1000000 Main: 100 RemoveTask threads have been launchedMain: Size of the List: 0
让我们看看它如何工作:
- 首先,你执行100个
AddTask
任务将元素添加到任务列表。每一个任务使用add()
方法插入10000个元素到列表,新增加的元素都会放到列表最后。当所有这些任务已经完成了,你会在控制台打印出了列表的元素数量。这时,这个列表有1000000个元素。 - 然后,你执行100个
RemoveTask
任务将元素从列表中删除。每一个任务删除这个列表用pollFirst()
和pollLast()
方法。pollFirst()方法返回和删除列表的第一个元素和pollLast()方法返回和删除最后一个元素的列表。如果列表为空,这些方法返回一个null值。当所有这些任务已经完成了,在控制台的打印出列表中元素的数量,这时,有零元素列表。 - 打印列表的元素的数量时,你使用了
size()
方法,你必须考虑,这种方法并不是真实的,特别是如果你使用它在线程进行列表中添加同时又删除数据。计数的方法遍历整个列表的元素和内容列表可以改变这个操作。一旦在你使用它们时没有任何线程修改列表,你可以保证返回的结果是正确的。
请注意, ConcurrentLinkedDeque
类提供了更多的方法来获取元素列表形式:
getFirst()
和getLast()
:这些方法返回分别从列表中第一个和最后一个元素。他们不会从列表中删除返回的元素。如果列表是空的,这些方法抛出一个NoSuchElementExcpetion
例外。peek()
,peekFirst()
,peekLast()
:这些方法返回列表的第一个和最后一个元素。他们不会从列表中删除返回的元素。如果列表为空,这些方法返回一个null值。remove()
,removeFirst()
,removeLast()
:这些方法返回列表的第一个和最后一个元素。他们从列表中移除返回的元素。如果列表是空的,这些方法抛出一个NoSuchElementException
例外。- 一个
ConcurrentLinkedDeque
是一个合适的选择,许多线程共享访问公共集合。 - 像大多数其他并发集合实现,这个类不允许null元素的使用。
- 迭代器是弱一致的,返回元素反映在一些点或双端队列的状态,因为迭代器的创建。他们不把
ConcurrentModificationException
与其他操作,可以同时进行。
转载地址:https://maokun.blog.csdn.net/article/details/80617880 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!
发表评论
最新留言
很好
[***.229.124.182]2024年04月29日 17时34分22秒
关于作者
喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
pure-ftp 启用虚拟账户的问题
2019-05-02
ipvsadm 安装配置
2019-05-02
linux下nc的使用
2019-05-02
sed学习---字符替换
2019-05-02
Linux shell脚本的字符串截取
2019-05-02
linux和windows下mysql密码怎样清空!
2019-05-02
mysql logs-slave-updates (A -> B -> C)
2019-05-02
关于Java中split方法对空字符串处理问题
2019-05-02
mysql JDBC URL参数解析
2019-05-02
数据库复习(4)
2019-05-02
C# TextBox输入密码显示星号(*)
2019-05-02
1小时点击量破千万!阿里巴巴首发:MySQL高级调优笔记!全是技术重点
2019-05-02
这个GItHub上的Java项目开源了 2021最全的Java架构面试复习指南
2019-05-02
Proftpd MySQL [Step by Step]
2019-05-02
EFI Shell 命令参考
2019-05-02
HP-UX oracle RAC 双机实践
2019-05-02
解决SHELL脚本中的export无法生效的问题【转】
2019-05-02
网络常用的linux系统调用【转】
2019-05-02