1.3.3 concurrent containers MAP / LIST / SET / QUEUE

HashMap

Index calculation: hashCode & (length-1), & bitwise AND operation, the same bit is a binary 1, which is only 1 bit

JDK1.7 JDK1.8 HashMap with the differences: JDK1.8 element when put, if the calculated chain length in the obtained index reaches 8:00 (the current count to be applied to the rear elements of the list), the list is converted into red black tree to improve search efficiency

ConcurrentHashMap

HashMap thread-safe

JDK1.7 ConcurrentHashMap HashTable composed of multiple, concurrent HashTable there are several levels of concurrencyLevel is a few default 16, which is called the segment lock,

ConcurrentSkipListMap/TreeMap

TreeMap except that the HashMap, TreeMap key of lexicographically ordered (ascending), can be achieved by sorting logic Comparator

TreeMap thread-safe, use ConcurrentSkipListMap guarantee thread safety

ArrayList

Non-thread-safe

CopyOnWriteArrayList

Thread-safe,

However, the array will be copied, at a certain time doubling the amount of data that cause memory overflow, data overload situation NA

Read the newly written data will be delayed, because the reference to the new needs of the array from the old array array

 

HashSet

HashMap if you encounter the same Key Value value will be overridden to ensure the HashMap Key is not repeated.

HashSet <T> i.e. HashMap This feature ensures the use of elements in the set Set (KEY) is not repeated, it is not concerned with the value of Value.

CopyOnWriteArraySet

 Write time will determine whether the array already exists, if there is no longer write, and other characteristics of the same CopyOnWriteArrayList

ConcurrentSkipListSet

 The principle of non-repetition jump table with ConcurrentSkipListMap, KEY and orderly

QUEUE queue

ArrayBlockingQueue

线程安全,数组实现,ReentrantLock锁,只有一把锁,take() 和 put() 互斥,加的是同一把锁;

构造函数制定队列长度capacity,利用参数count记录队列中元素数量,count=capacity时put操作阻塞,count=0时take操作阻塞,底层唤醒其实是利用condition的2个队列实现,参照1.3.1 Lock利用condition实现的阻塞队列;

put和take时利用takeIndex和putIndex记录下一个操作应该放到那个位置或从哪个位置取;

循环数组实现:当putIndex达到capacity时,takeIndex并不是+1,而是变成0,即下一个put操作会将元素放到队列头部;takeIndex原理相同

 

LinkedBlockingQueue

线程安全,链表实现,有读锁和写锁2把锁,读和写操作加的是不同的锁,互不干扰,提高了读写性能

ConcurrentLinkedQueue

线程安全,并发度高,非阻塞队列,无锁,没有take() 和 put()这2个阻塞方法

利用CAS操作,采用自旋的方式将元素添加到链表尾部 或 将链表头部替换为null

SynchronousQueue

不常用

package com.study.list_set_queue.queue;

import java.util.concurrent.SynchronousQueue;

/*
1、take会阻塞,直到取到元素
2、put时会阻塞,直到被get
3、若没有take方法阻塞等待,offer的元素可能会丢失
4、poll取不到元素,就返回null,如果正好有put被阻塞,可以取到
5、peek 永远只能取到null,不能让take结束阻塞

 */

public class Demo2_SyncQueueTest {
    static SynchronousQueue<String> syncQueue = new SynchronousQueue<>();

    //put时会阻塞,直到被get
    public static void test01() throws InterruptedException {
        new Thread(){
            @Override
            public void run() {
                try {
                    Thread.sleep(3000L);
                    System.out.println(syncQueue.poll());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        System.out.println("begain to put...");
        syncQueue.put("put_element");
        System.out.println("put done...");
    }

    //3、若没有take方法阻塞等待,offer的元素可能会丢失
    public static void test02() throws InterruptedException {
        syncQueue.offer("offered_element");

        System.out.println(syncQueue.poll());
    }

    //4、poll取不到元素,就返回null,如果正好有put被阻塞,可以取到
    public static void test03() throws InterruptedException {
/*        new Thread(){
            @Override
            public void run() {
                try {
                    syncQueue.put("put_element");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();*/

        Thread.sleep(200L);
        Object obj =  syncQueue.poll();
        System.out.println(obj);
    }

    //peek 永远只能取到null,不能让take结束阻塞
    public static void test04() throws InterruptedException {
        new Thread(){
            @Override
            public void run() {
                try {
                    syncQueue.put("put_element");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();

        Thread.sleep(200L);
        Object obj =  syncQueue.peek();
        System.out.println(obj);
    }


    public static void main(String args[]) throws InterruptedException {
        test02();
    }
}

PriorityBlockingQueue

优先级队列,可以通过比较器对入队列的元素进行排序存储,进而改变出队列顺序

package com.study.list_set_queue.queue;

import java.util.Comparator;
import java.util.concurrent.PriorityBlockingQueue;

public class Demo4_PriorityBlockingQueue3 {
	public static void main(String args[]) {
		PriorityBlockingQueue<Student> queue = new PriorityBlockingQueue<>(5, new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				int num1 = o1.age;
				int num2 = o2.age;

				if (num1 > num2)
					return 1;
				else if (num1 == num2)
					return 0;
				else
					return -1;
			}
		});
		queue.put(new Student(10, "enmily"));
		queue.put(new Student(20, "Tony"));
		queue.put(new Student(5, "baby"));

		for (; queue.size() > 0;) {
			try {
				System.out.println(queue.take().name);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}

class Student {
	public int age;
	public String name;

	public Student(int age, String name) {
		this.age = age;
		this.name = name;
	}
}

 

Guess you like

Origin www.cnblogs.com/yfzhou528/p/11297646.html