美文网首页
Java并发容器类

Java并发容器类

作者: maven_hz | 来源:发表于2017-08-09 21:26 被阅读0次

    Map or Set

    • 并发要求低时加锁容器类:
      Hashtable //用的少
      Collections.sychronizedMap(new HashMap())
      Collections.sychronizedList ...
      例:

      List<String> strsSync = Collections.synchronizedList(new ArrayList());
      
    • 并发要求高时加锁容器类:
      ConcurrentHashMap
      分段加锁(大锁分成小锁)。不同块之间可以同时执行
      并发要求高并需要排序:
      ConcurrentSkipListMap
      跳表查询,查找效率高。跳表:每个元素上有多个指针,指向后面多个节点,进行跳跃查询。比如查找 19.从6 开始比较。大于6.直接跳到9.越过了7.从时间复杂度来讲。从O(n)变为了O(n/2)

    队列

    Collections.synchronizedXXX
    CopyOnWriteList:
    写时复制容器。写时效率很低。读时效率高。写时加锁,读不加锁。写的时候复制一份数据,并在这份数据上做更改,再把指针指向换到新数据中。读写分离的思路。

    Queue: 分两种:1.加锁的Queue 2.Blocking Queue

    1. CocurrentLinkedQueue //concurrentArrayQueue
      例:
        Queue<String> strs = new ConcurrentLinkedQueue<>();
            
            for(int i=0; i<10; i++) {
                strs.offer("a" + i);  //add 有boolean返回值来判断插入是否成功
            }
            System.out.println(strs.size()); //10
            
            System.out.println(strs.poll());//a0 ;拿取第一个。并删除。先进先出
            System.out.println(strs.size());//9
            
            System.out.println(strs.peek());//a1 ;拿取第一个。不删除
            System.out.println(strs.size());// 9
    
    1. BlockingQueue:阻塞队列
      LinkedBlockingQueue
      ArrayBlockingQueue
      例:
        public class LinkedBlockingQueue {
    
        static BlockingQueue<String> strs = new LinkedBlockingQueue<>(10);
    
        static Random r = new Random();
    
        public static void main(String[] args) {
            new Thread(() -> {
                for (int i = 0; i < 100; i++) {
                    try {
                        strs.put("a" + i); //如果满了,就会等待
                        System.out.println("now size:"+strs.size()); //永远不会超过10个长度
                        TimeUnit.MILLISECONDS.sleep(r.nextInt(1000));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "p1").start();
    
            for (int i = 0; i < 5; i++) {
                new Thread(() -> {
                    for (;;) {
                        try {
                            System.out.println(Thread.currentThread().getName() + " take -" + strs.take()); //如果空了,就会等待。不会出现IndexOutOfBoundException
                            TimeUnit.MILLISECONDS.sleep(r.nextInt(10000));
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }, "c" + i).start();
    
            }
        }
    }
    

    往容器内加入方法有多个,如下

    strs.put("aaa"); //满了就会等待,程序阻塞
    strs.add("aaa"); //报异常
    strs.offer("aaa"); //不会报异常。只会在返回值中返回true or false
    strs.offer("aaa", 1, TimeUnit.SECONDS);//等待一秒再加入
    

    TransferQueue :队列有消费者等待消费时,直接把信息给消费者,不进入队列,高并发下效率更高,适用于游戏服务器接收,转发消息。如果没有消费者等待消费该队列,这时strs.transfer("aaa"); 线程将阻塞。但是put add 方法都不会阻塞。netty中使用比较多,很多实时消息需要强制被消费之后才执行下面操作。
    SynchronusQueue : 容量为0,只能调用strs.put("aaa") 进行加入,目的是为了进入阻塞状态,等待被消费。是必须被消费的,不能存在队列中。如调用add()将提示队列已满
    DelayQueue : 可作为执行定时任务 按指定的时间,顺序消费,delay时间越短的越早消费

    相关文章

      网友评论

          本文标题:Java并发容器类

          本文链接:https://www.haomeiwen.com/subject/vwdqrxtx.html