zoukankan      html  css  js  c++  java
  • Concurrent包详解及使用场景

    Concurrent包是jdk1.5所提供的一个针对高并发进行编程的包。

    1.阻塞式队列 - BlockingQueue

    遵循先进先出(FIFO)的原则。阻塞式队列本身使用的时候是需要指定界限的。

    在生产者消费者模型中,生产数据和消费数据的速率不一致,如果生产数据速度快一些,消费(处理)不过来,就会导致数据丢失。这时候我们就可以应用上阻塞队列来解决这个问题。

    ArrayBlockingQueue - 阻塞式顺序队列

    底层是基于数组来进行存储,使用的时候需要指定一个容量,容量指定之后不可改变。--- 生产 - 消费模型

        public static void main(String[] args) throws InterruptedException {
    
            // 这个队列在创建的时候需要指定容量,容量在指定之后不可变
            ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<>(5);
    
            // 添加队列
            queue.add("a");
            queue.add("b");
            queue.add("c");
            queue.add("d");
            queue.add("e");
    
            // 如果队列已满,则抛出异常 - IllegalStateException
            // queue.add("a");
            // 返回值标记元素是否成功添加到队列里面
            // 如果队列已满,则返回false
            // boolean b = queue.offer("b");
            // System.out.println(b);
            // 如果队列已满,会产生阻塞 --- 直到这个队列中有元素被取出,才会放开阻塞
            // queue.put("c");
    
            // 定时阻塞
            // 在3s之内如果有元素被取出,那么元素就会添加到队列中
            // 如果3s之后队列依然是满的,那么返回false表示添加失败
            boolean b = queue.offer("d", 3000, TimeUnit.MILLISECONDS);
            System.out.println(b);
            System.out.println(queue);
        }

    LinkedBlockingQueue - 阻塞式链式队列

    底层是基于链表(节点)来进行数据的存储。在使用的时候可以指定初始容量,也可以不指定。

    如果指定了容量,就以指定的容量为准来进行存储;

    如果不指定容量,那么默认容量是 Integer.MAX_VALUE -> 231 - 1。如果不指定容量,一般认为这个容量是无限的。

    PriorityBlockingQueue - 具有优先级的阻塞式队列

    如果不指定容量,默认容量是11.如果将元素取出,那么会对元素进行自然排序 --- 要求存储的对象所对应的类必须实现Comparable,重写compareTo方法,讲比较规则写到方法中;如果进行迭代遍历,那么不保证排序。

    SynchronousQueue - 同步队列

    只允许存储1个元素。

    2.并发映射 - ConcurrentMap

    HashMap - 底层依靠数组+链表存储的数据

    默认初始容量是16,默认加载因子是0.75f,默认扩容每次增加一倍。本身是一个异步式线程不安全的映射

    Hashtable - 同步式线程安全的映射

    对外提供的方法都是同步方法

    ConcurrentHashMap - 异步式线程安全的映射

    在jdk1.8之前,采用分段(分桶)锁, 分段锁采用的是读写锁机制(读锁:允许多个线程读,但是不允许线程写;写锁:允许一个线程写,但是不允许线程读);jdk1.8不再采用锁机制,而是CAS(Compare and Swap)算法, 减小了锁的开销;如果一个桶中的元素个数超过了8个,那么会将这个桶的链表扭转成一棵红黑树(自平衡二叉查找树)结构。

    ConcurrentNavigableMap - 并发导航映射

    本身是一个接口,所以更多的是使用实现类

    ConcurrentSkipListMap - 并发跳跃表映射

    跳跃表:为了提高查询效率所产生的一种数据结构

    跳跃表是典型的以空间换时间的产物。

    跳跃表的时间复杂度是O(logn)

    如果跳跃表中插入新的元素,新的元素是否往上提取,遵循“抛硬币”原则 --- 1/2原则

    只要保证这个节点有一半的概率被提取就可以

    跳跃表适合大量查询而不增删的场景

    CountDownLatch - 闭锁 - 线程减锁

    对线程neg进行计数,当计数归零的时候会开放阻塞线程继续往下执行

    public class CountDownLatchDemo {
        
        public static void main(String[] args) throws InterruptedException {
            
            CountDownLatch cdl = new CountDownLatch(5);
            
            new Thread(new Teacher(cdl)).start();
            new Thread(new Student(cdl)).start();
            new Thread(new Student(cdl)).start();
            new Thread(new Student(cdl)).start();
            new Thread(new Student(cdl)).start();
            
            // 表示让线程阻塞,直到计数归零的时候阻塞才能放开
            cdl.await();        
            System.out.println("考试结束~~~");      
        }
    }
    
    class Student implements Runnable {
        
        private CountDownLatch cdl;
    
        public Student(CountDownLatch cdl) {
            this.cdl = cdl;
        }
    
        @Override
        public void run() {
            
            System.out.println("学生来到考场,准备考试~~~");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            
            System.out.println("学生交卷离开考场");
            
            // 计数-1
            cdl.countDown();
        }
    }
    
    class Teacher implements Runnable {
        
        private CountDownLatch cdl;
    
        public Teacher(CountDownLatch cdl) {
            this.cdl = cdl;
        }
    
        @Override
        public void run() {
    
            System.out.println("老师来到考场,准备考试~~~");
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("老师收卷离开了考场~~~");
            
            cdl.countDown();
        }
    }

     

     

     

     

     

     

     

     

     

     

     

     

     

     

     

  • 相关阅读:
    HBase with MapReduce (MultiTable Read)
    HBase with MapReduce (SummaryToFile)
    HBase with MapReduce (Summary)
    HBase with MapReduce (Read and Write)
    HBase with MapReduce (Only Read)
    Hbase中的BloomFilter(布隆过滤器)
    HBase的快照技术
    How To Use Hbase Bulk Loading
    Cloudera-Manager修改集群的IP
    Java中的HashSet和TreeSet
  • 原文地址:https://www.cnblogs.com/chuijingjing/p/10072912.html
Copyright © 2011-2022 走看看