Java中常用的集合框架

BlockingQueue

A线程可以知道b线程的存在

是一个接口并非一个具体实现:

ArrayBlockingQueue

ArrayBlockingQueue的内部元素都放置在一个对象数组中:final Object[] items;

Offer():当队列已经满了,会立即返回false

Put():如果队列满了会一直等待

Pool():弹出元素,如果为空返回null

Take():弹出元素,如果为空等待到有元素即可。

Take方法:

public E take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == 0)
                notEmpty.await();
            return extract();
        } finally {
            lock.unlock();
        }
    }
    
private void insert(E x) {
        items[putIndex] = x;
        putIndex = inc(putIndex);
        ++count;
        notEmpty.signal();
    }

Put方法:

public void put(E e) throws InterruptedException {
        checkNotNull(e);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            while (count == items.length)
                notFull.await();
            insert(e);
        } finally {
            lock.unlock();
        }
    }
/**
     * Extracts element at current take position, advances, and signals.
     * Call only when holding lock.
     */
    private E extract() {
        final Object[] items = this.items;
        E x = this.<E>cast(items[takeIndex]);
        items[takeIndex] = null;
        takeIndex = inc(takeIndex);
        --count;
        notFull.signal();
        return x;
    }

LinkedBlockingQueue(锁分离)

两把不同的锁
/** Lock held by take, poll, etc */
    private final ReentrantLock takeLock = new ReentrantLock();
 
    /** Wait queue for waiting takes */
    private final Condition notEmpty = takeLock.newCondition();
 
    /** Lock held by put, offer, etc */
    private final ReentrantLock putLock = new ReentrantLock();
 
    /** Wait queue for waiting puts */
    private final Condition notFull = putLock.newCondition();
 
Take函数
public E take() throws InterruptedException {
        E x;
        int c = -1;
        final AtomicInteger count = this.count;
        final ReentrantLock takeLock = this.takeLock;
        takeLock.lockInterruptibly();//不能有两个线程同时取数据
        try {
            while (count.get() == 0) {//如果没有数据,一直等待(因为是lockInterruptibly,可中断)
                notEmpty.await();
            }
            x = dequeue();//取得第一个数据
            c = count.getAndDecrement();//数量-1,原子操作,因为会和put同时访问count。
            if (c > 1)
                notEmpty.signal();//通知其他take操作
        } finally {
            takeLock.unlock();//释放锁
        }
        if (c == capacity)
            signalNotFull();//通知put操作,已有空余空间
        return x;
    }
 
Put函数
public void put(E e) throws InterruptedException {
        if (e == null) throw new NullPointerException();
        // Note: convention in all put/take/etc is to preset local var
        // holding count negative to indicate failure unless set.
        int c = -1;
        Node<E> node = new Node(e);
        final ReentrantLock putLock = this.putLock;
        final AtomicInteger count = this.count;
        putLock.lockInterruptibly();//上锁不能有两个线程同时进行put函数
        try {
            /*
             * Note that count is used in wait guard even though it is
             * not protected by lock. This works because count can
             * only decrease at this point (all other puts are shut
             * out by lock), and we (or some other waiting put) are
             * signalled if it ever changes from capacity. Similarly
             * for all other uses of count in other wait guards.
             */
            while (count.get() == capacity) {//当队列已经满了以后,等待
                notFull.await();
            }
            enqueue(node);//插入数据
            c = count.getAndIncrement();//更新总数
            if (c + 1 < capacity)
                notFull.signal();//有足够的空间,通知其他线程
        } finally {
            putLock.unlock();//释放锁
        }
        if (c == 0)
            signalNotEmpty();//释放成功后,通知take函数取数据
    }

并发下的ArrayList

当ArrayList在扩容的时候,内部一致性被破坏,由于没有锁的保护,另外一个线程访问不到不一致的内部状态,导致出现越界问题。

还会出现多个线程同时对同一位置进行赋值。

concurrentlinkedqueue

concurrentlinkedqueue:

高并发环境中可以说是最好的队列,也可以看做是一个线程安全的linkedList。

CopyOnWriteArrayList

性能很好的读写list,在读写的时候任何时候都不加锁;只有在写写的时候需要同步等待。

当写操作的时候,进行一次自我复制。对原有的数据进行一次复制,将修改的内容写入副本修改完之后,将副本替换原来的数据。

PriorityQueue

PriorityQueue也叫优先队列,所谓优先队列指的就是每次从优先队列中取出来的元素要么是最大值(最大堆),要么是最小值(最小堆)。我们知道,队列是一种先进先出的数据结构,每次从队头出队(移走一个元素),从队尾插入一个元素(入队)。

ArrayDeque(一种双端队列)

参考:http://blog.csdn.net/qq_35326718/article/details/72972159

原文地址:http://blog.51cto.com/qinbin/2068856

时间: 2024-07-30 04:33:29

Java中常用的集合框架的相关文章

[转]Java中常用的集合—初学者的你不可错过的精编整理

集合一直都是项目中非常常见的,我是一个Android开发者,集合对于我来说,在项目中使用的次数非常之多,因为使用的多,熟能生巧,所以这里呢!就给那些初学者整理一下Java当中常用的集合吧!   因为此篇文章是给初学者看到,所以对于集合的认识,我们就不从内存的角度去分析了,等你Java学到一定的时候,再去学习一下集合的底层实现,这会让成为一名更加牛的Java程序员.   在整理之前呢,我们先聊一聊为什么集合会这么常用?,集合这个概念,我们初次接触是在高中的数学当中,高中的集合具有以下知识点:  1

Java中泛型在集合框架中的应用

泛型是Java中的一个重要概念,上一篇文章我们说过,当元素存入集合时,集合会将元素转换为Object类型存储,当取出时也是按照Object取出的,所以用get方法取出时,我们会进行强制类型转换,并且通过代码也可以看出来,我们放入其他类型时,如字符串,编译器不会报错,但是运行程序时会抛出类型错误异常,这样给开发带来很多不方便,用泛型就解决了这个麻烦 泛型规定了某个集合只能存放特定类型的属性,当添加类型与规定不一致时,编译器会直接报错,可以清楚的看到错误 当我们从List中取出元素时直接取出即可,不

Java中常见的集合框架

1. 一.collection (有序)接口的实现的接口 set  list 其中set接口的实现类是HashSet,List接口的实现类是ArrayList.LinkList.Vector 二.Map(无序)接口的实现类是HashMap.HashTable ArrayList和Vector都是使用数组方式存储数据,此数组元素数大于实际存储的数据以便增加和插入元素,它们都允许直接按序号索引元素,但是插入元素要涉及数组元素移动等内存操作,所以索引数据快而插入数据慢,Vector由于使用了synch

Java中常用的集合

  有序列 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否 否 HashSet TreeSet 是(用二叉树排序) Map AbstractMap 否 使用key-value来映射和存储数据, Key必须惟一,value可以重复 HashMap TreeMap 是(用二叉树排序) 几个面试常见问题:1.Q:ArrayList和Vector有什么区别?HashMap和HashTable有什么区别?A:Vector和HashTable是线程同步的(

第五节:Java中常用数据集合

List public interface List<E>extends Collection<E> 有序的 collection(也称为序列),允许重复的元素. 常用实现类: ArrayList: 底层使用的是数组结构,特点:查询速度快,增删操作较慢,而且线程不同步. 要保证同步,可以使用:List list = Collections.synchronizedList(new ArrayList());进行包装,默认容量为10. 常用方法:add,addAll,remove,i

【知了堂学习笔记】java中常用集合的理解

最近学习了java中常用集合类的一些知识,在这里作为一只小白,我来谈谈我的理解,顺带总结知识点. 引入:在没有接触之前,听到集合,给我感觉是想到了数学中的集合一样,里面存放着一个一个的元素.其实不然,这个集合也就差不多,是用来存放元素的容器. Java中的集合类包含的内容很多而且很重要,很多数据的存储和处理(排序,去重,筛选等)都需要通过集合类来完成. 今天我要谈的主要是,如下图所示: 1.Collection Collection是最基本的集合类型,若要检查Collection中的元素,可以使

java中常用的包及作用

1. java.awt:提供了绘图和图像类,主要用于编写GUI程序,包括按钮.标签等常用组件以及相应的事件类. 2. java.lang:java的语言包,是核心包,默认导入到用户程序,包中有object类,数据类型包装类,数学类,字符串类,系统和运行时类,操作类,线程类,错误和异常处理类,过程类. 3. java.io:包含提供多种输出输入功能的类. 4. java.net: 包含执行与网络有关的类,如URL,SCOKET,SEVERSOCKET等. 5. java.applet:包含java

开发java中常用的几种数据类型

JAVA中常用的数据结构(java.util. 中) java中有几种常用的数据结构,主要分为Collection和map两个主要接口(接口只提供方法,并不提供实现),而程序中最终使用的数据结构是继承自这些接口的数据结构类.其主要的关系(继承关系)有:  (----详细参见java api文档!) Collection---->Collections                                                                          

java中常用的工具类(二)

下面继续分享java中常用的一些工具类,希望给大家带来帮助! 1.FtpUtil Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71