并发

Java线程同步类容器和并发容器(四)

目录1容器集简单介绍2同步容器3并发容器4案例讲解4.3.1ConcurrentLinkedQueue4.3.2阻塞队列LinkedBlockingQueue4.3.3BlockingQueue4.3.4延时队列DelayQueue4.3.5转移队列LinkedTransferQueue4.3.6SynchronousQueue4.1Map/Set4.2List4.3Queue1容器集简单介绍ja

目录

1 容器集简单介绍

java.util包下面的容器集主要有两种,一种是Collection接口下面的List和Set,一种是Map,
大致结构如下:

  • Collection

    • HashSet

    • TreeSet

    • LinkedSet

    • LinkedList

    • ArrayList

    • Vector

    • Stack

    • List

    • Set

  • Map

    • Hashtable

    • HashMap

    • WeakHashMap

2 同步容器

同步容器也叫线程安全容器,是通过syncrhoized关键字对线程不安全的操作进行加锁来保证线程安全的
其中同步容器主要包括:
1.Vector、Stack、HashTable
2.Collections 工具类中提供的同步集合类
Collections类是一个工具类,相当于Arrays类对于Array的支持,Collections类中提供了大量对集合或者容器进行排序、查找的方法。它还提供了几个静态方法来创建同步容器类:

3 并发容器

java.util.concurrent提供了多种线程安全容器,大多数是使用系统底层技术实现的线程安全,也叫并发容器,类似native。Java8中使用CAS。

4 案例讲解

这里主要介绍一些常见的同步容器和并发容器,通过案例输出结果对比进行介绍
我大致分为了三类Map/Set,List,Queue来进行讲解,但一个Map/Set,只介绍了Map,因为在java的设计中,Set就是Map,说白了就是只有Key没有Value的Map,好了,现在开始进入正题

4.1 Map/Set

代码中new了三个Map,HashTable,ConcurrentHashMap,ConcurrentSkipListMap比较每个map的运行效率,起100个线程向map中存放10000条随机数,并通过门闩CountDownLatch控制运行状态,输出运行时间

/**
 * 并发容器 - ConcurrentMap
 */package com.bernardlowe.concurrent.t06;import java.util.HashMap;import java.util.Hashtable;import java.util.Map;import java.util.Random;import java.util.concurrent.ConcurrentHashMap;import java.util.concurrent.ConcurrentSkipListMap;import java.util.concurrent.CountDownLatch;public class Test_01_ConcurrentMap {
    
    public static void main(String[] args) {
        final Map<String, String> map = new Hashtable<>();        // final Map<String, String> map = new ConcurrentHashMap<>();
        // final Map<String, String> map = new ConcurrentSkipListMap<>();
        final Random r = new Random();
        Thread[] array = new Thread[100];
        final CountDownLatch latch = new CountDownLatch(array.length);        
        long begin = System.currentTimeMillis();        for(int i = 0; i < array.length; i++){            array[i] = new Thread(new Runnable() {
                @Override                public void run() {                    for(int j = 0; j < 10000; j++){                        map.put("key"+r.nextInt(100000000), "value"+r.nextInt(100000));
                    }
                    latch.countDown();
                }
            });
        }        for(Thread t : array){
            t.start();
        }        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }        long end = System.currentTimeMillis();
        System.out.println("执行时间为 : " + (end-begin) + "毫秒!");
    }

}

Hashtable结果:

ConcurrentHashMap结果:

ConcurrentSkipListMap结果:

ConcurrentHashMap的底层是哈希实现的同步Map(Set)
ConcurrentSkipListMap内部是SkipList(跳表)结构实现的非阻塞读/写/删除 的 Map,它的value是有序存储的, 而且其内部是由纵横链表组成,在JDK1.8中,ConcurrentHashMap的性能和存储空间要优于ConcurrentSkipListMap

为了让测试数据结果对比更加直观,我这里故意将生成的随机数调的比较大。这里需要注意一下,在测试的时候,如果机器性能比较好,可能结果会出现误差,因为System.currentTimeMillis(),这个方法调用了个native方法,获取的时间精度会依赖于操作系统的实现机制,具体为什么,可以看看这篇文章http://blog.sina.com.cn/s/blog_6b8bd9d80101fe8t.html。但我按照文档的办法将System.currentTimeMillis()改为System.nanoTime(),发现并没有解决这个问题,可能是因为并没有达到纳秒级别吧。

4.2 List

下面代码与4.1的代码类似,也是new了三个List,ArrayList,Vector,CopyOnWriteArrayList,起100个线程向map中存放1000条随机数,并通过门闩CountDownLatch控制运行状态,输出运行时间和最后list的的长度。由于ArrayList是线程不安全,在多线程执行的时候,需要try{}catch{},否则会因为数组越界而报错,因为ArrayList底层是一个长度动态扩展的数组

/**
 * 并发容器 - CopyOnWriteList
 */package com.bernardlowe.concurrent.t06;import java.util.ArrayList;import java.util.List;import java.util.Random;import java.util.Vector;import java.util.concurrent.CopyOnWriteArrayList;import java.util.concurrent.CountDownLatch;public class Test_02_CopyOnWriteList {
    
    public static void main(String[] args) {
         final List<String> list = new ArrayList<String>(); // 线程不安全//       final List<String> list = new Vector<>(); // 线程安全//      final List<String> list = new CopyOnWriteArrayList<>(); // 线程安全
        final Random r = new Random();
        Thread[] array = new Thread[100];
        final CountDownLatch latch = new CountDownLatch(array.length);        
        long begin = System.currentTimeMillis();        for(int i = 0; i < array.length; i++){            array[i] = new Thread(new Runnable() {
                @Override                public void run() {                    for(int j = 0; j < 1000; j++){                        try {                            list.add("value" + r.nextInt(100000));
                        } catch (Exception e) {

                        }
                    }
                    latch.countDown();
                }
            });
        }        for(Thread t : array){
            t.start();
        }        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }        long end = System.currentTimeMillis();
        System.out.

原创不易,完成人机校验,阅读全文

相关推荐