赞
踩
一、介绍
在编程语言中,数据结构是一种能为计算机提供数据存储的元素,在java语言中,提供了集合框架,实现不同类型的数据结构的属性,类和接口等,可以应用于程序中。
在并发编程中,常用的大多数集合并不适用,因为它们没有控制数据
的并发访问,当多个并发线程访问同一个共享的数据结构时,会造成数据的不正确性。比如ArrayList,HashMap等。
(1)、当然java提供了可以在并发中使用的,不会出现问题且可保证数据一致的集合,可以分为如下两种:
1.阻塞集合
这种集合包括添加和删除数据的操作。如果操作不能立即进行,是因为集合已满或者为空,该程序将被阻塞,直到操作可以进行。
2.非阻塞集合
这种集合也包括添加和删除数据的操作。如果操作不能立即进行,这个操作将返回null值或抛出异常,但该线程将不会阻塞。
(2)、在并发编程中常用的一些集合列表:
非阻塞列表,使用ConcurrentLinkedDeque类。
阻塞列表,使用LinkedBlockingDeque类。
用在生产者与消费者数据的阻塞列表,使用LinkedTransferQueue类。
使用优先级排序元素的阻塞列表,使用PriorityBlockingQueue类。
存储延迟元素的阻塞列表,使用DelayQueue类。
非阻塞可导航的map,使用ConcurrentSkipListMap类。
随机数,使用ThreadLocalRandom类。
原子变量,使用AtomicLong和AtomicIntegerArray类。
二、非阻塞线程安全列表
(1)、列表(List):是最基本的线性集合元素,一个列表有不确定的元素数量,并且你可以添加、读取和删除任意位置上的元素。并发列表允许不同的线程在同一时刻对列表的元素进行添加或删除,而不会产生任何数据不一致(问题)。
(2)、ConcurrentLinekedQueue的使用,它是非阻塞的,若操作不能立即完成,它将根据此操作返回null或抛出异常。
下面来实现一个例子:
1.往列表中大量添加数据;
2.在同个列表中,进行数据的大量删除
程序实现:
1.增加任务类
public class AddTask implements Runnable {
private ConcurrentLinkedDeque list;
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+":"+i);
}
}
}
2.删除任务类
public class PollTask implements Runnable {
private ConcurrentLinkedDeque list;
public PollTask(ConcurrentLinkedDeque list){
this.list=list;
}
@Override
public void run() {
for(int i=0;i<5000;i++){
list.pollFirst();
list.pollLast();
}
}
}
3.测试类
@Test
public void tesConcurrentLinkedDeque(){
ConcurrentLinkedDeque list=new ConcurrentLinkedDeque();
Thread threads[]=new Thread[100];
for(int i=0;i
AddTask task=new AddTask(list);
threads[i]=new Thread(task);
threads[i].start();
}
//使用join方法等待这些线程的完成
for(int i=0;i
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Size of the List: %d\n",list.size());
for (int i=0; i
PollTask task=new PollTask(list);
threads[i]=new Thread(task);
threads[i].start();
}
System.out.printf("Main: %d PollTask threads have been launched\n",threads.length);
//使用join方法等待这些线程的完成
for(int i=0;i
try {
threads[i].join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Size of the List: %d\n",list.size());
}
4、运行结果
(3)、 实现说明: 1.创建100个增加任务的线程(AddTask),将并发的list初始化到线程中 2.每个线程会在list的尾部插入新的元素,插入10000个元素,则list的大小为 3.用join方法等待线程创建完成,才开始执行下面操作 4.创建100个删除任务的线程(PollTask) 5.每个PollTask会执行pollFirst()删除头部元素,执行pollLast()删除尾部元素,若列表为空,则返回null 6.利用list的size()方法,打印列表元素中的量。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。