java容器及其并发容器的演进

   static List<String> arrayList = new ArrayList();

    static {
        for (int i = 0; i < 10000; i++) {
            arrayList.add("编号:" + i);
        }
    }  

 //会出现多线线程处理同一个元素
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                while (arrayList.size() > 0) {
                    System.out.println("售票--" + arrayList.remove(0));
                }
            }).start();
        }

  

  static Vector<String> vector = new Vector<>();

    static {
        for (int i = 0; i < 10000; i++) {
            vector.add("编号:" + i);
        }
    }


 //线程安全的容器
        //在判断vector.size() 与remove移除之间没有枷锁 还是会出现超卖现象
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                while (vector.size() > 0) {
                    try {
                        TimeUnit.MILLISECONDS.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("售票--" + vector.remove(0));
                }
            }).start();
        }

  

   static LinkedList<String> linkList = new LinkedList<>();

    static {
        for (int i = 0; i < 1000; i++) {
            linkList.add("编号:" + i);
        }
    }



        //线程安全的容器  枷锁
//        给整个容器加上锁 每个线程都获取对象linkList锁  但是效率比较低
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                while (true) {
                    synchronized (linkList) {
                        if (linkList.size() <=0) break;
                        try {
                            TimeUnit.MILLISECONDS.sleep(10);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println("售票--" + linkList.remove(0));
                    }
                }
            }).start();
        }

  

 

 

   static Queue<String> queue = new ConcurrentLinkedDeque<>();

    static {
        for (int i = 0; i < 10000; i++) {
            queue.add("编号:" + i);
        }
    }


 //多线程访问单个元素  并发性能较好的方式
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                while (true) {
                    String poll = queue.poll();
                    if (poll == null) break;
                    else System.out.println("售票--" + poll);
                }
            }).start();
        }

  

 

思考:LinkedList与ConcurrentLinkedDeque有何区别?

  

   /**
         * LinkedList的内部数据结构
         * 基于链表实现:LinkedList是一个双向链表,每个节点包含三个部分:元素本身、指向前一个节点的引用(prev)和指向后一个节点的引用(next)。这种结构使得在链表中间插入和删除元素相对高效,因为只需要修改相关节点之间的引用关系。
         * 非线程安全的结构设计:它没有内置的并发控制机制。在多线程环境下,如果多个线程同时访问和修改LinkedList,比如一个线程在遍历链表,另一个线程在删除某个节点,就可能导致数据不一致或者抛出ConcurrentModificationException。
         * ConcurrentLinkedDeque的内部数据结构
         * 也是基于链表实现的双端队列:ConcurrentLinkedDeque同样是一个链表结构,并且是双向的。每个节点也有元素本身、指向前一个节点的引用和指向后一个节点的引用。不过,它采用了更加复杂的算法来实现无锁并发访问。
         * 使用无锁算法和 CAS 操作:它利用了 CAS 操作来实现并发安全。在插入和删除元素时,通过原子性的比较和交换操作来更新节点的引用。例如,当插入一个新元素时,会尝试以原子方式更新相关节点的引用,以确保数据的一致性和并发安全性。这种设计使得多个线程可以同时对队列进行操作,而不会像传统的加锁机制那样造成阻塞。
         * 节点标记和辅助机制用于并发控制:ConcurrentLinkedDeque还采用了一些特殊的节点标记和辅助手段来帮助管理并发操作。例如,节点可能会有一些标记来指示其状态(如是否已经被逻辑删除等),这些标记在并发操作过程中发挥着重要作用,以保证在高并发环境下队列的正常运行。
         */

  

posted @ 2024-12-30 10:26  余生请多指教ANT  阅读(8)  评论(0)    收藏  举报