并发编程(四)—并发集合(一)

一、介绍

在编程语言中,数据结构是一种能为计算机提供数据存储的元素,在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;inew AddTask(list);
            threads[i]=new Thread(task);
            threads[i].start();
        }
        //使用join方法等待这些线程的完成
        for(int i=0;itry {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("Size of the List: %d\n",list.size());
        for (int i=0; inew 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;itry {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.printf("Size of the List: %d\n",list.size());
    }

4、运行结果
并发编程(四)—并发集合(一)_第1张图片

(3)、 实现说明:
1.创建100个增加任务的线程(AddTask),将并发的list初始化到线程中
2.每个线程会在list的尾部插入新的元素,插入10000个元素,则list的大小为
3.用join方法等待线程创建完成,才开始执行下面操作
4.创建100个删除任务的线程(PollTask)
5.每个PollTask会执行pollFirst()删除头部元素,执行pollLast()删除尾部元素,若列表为空,则返回null
6.利用list的size()方法,打印列表元素中的量。

你可能感兴趣的:(并发编程)