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还采用了一些特殊的节点标记和辅助手段来帮助管理并发操作。例如,节点可能会有一些标记来指示其状态(如是否已经被逻辑删除等),这些标记在并发操作过程中发挥着重要作用,以保证在高并发环境下队列的正常运行。 */
标签:容器,java,++,并发,static,new,线程,节点 From: https://www.cnblogs.com/wangbiaohistory/p/18640293