zoukankan      html  css  js  c++  java
  • Java-JUC(四):同步容器介绍

    同步容器简介

    针对容器我们知道有HashMap,HashTable,其中HashMap是一个非线程安全的,HashMap在并发执行put操作时会引起死循环,导致CPU利用率接近100%。因为多线程会导致HashMap的Node链表形成环形数据结构,一旦形成环形数据结构,Node的next节点永远不为空,就会在获取Node时产生死循环,而且死循环发生在发生在扩容时

    HashTable是线程安全的,但是在复合操作上会线程不安全的现象。

    备注:

    1)什么是复合操作?比如添加元素,需先判断是否元素存在,元素不存在时才添加。

    2)hashtable是在插入和删除上都是索表的方式,因此效率特别低。

    在jdk1.5之后提供java.util.concurrent包下的一些同步容器:java.util.concurrent.ConcurrentHashMap<K, V>。

    ConcurrentHashMap性能讲解:

    ConcurrentHashMap的性能要比HashTable性能高,而且高很多。

    1)ConcurrentHashMap在jdk1.7之前采用了“锁分段”机制,默认把一个ConcurrentHashMap分为16个segment,每个segment下默认也是长度为16的哈希表,在每个哈希元素下是链表。这样就可默认每段有一个锁,一次可以最大并发操作16。

    2)在jdk1.8之后ConcurrentHashMap采用CAS算法,可以把CAS算法错略的认为是无锁算法。

    3)java.util.concurrent包还提供了设计用于多线程上下文中的Collection实现:ConcurrentHashMap、ConcurrentSkipListMap、ConcurrentSkipListSet、CopyOnWriteArrayList和CopyOnWriteArraySet。

    4)当希望许多线程访问一个给定的Collection时

      a)ConcurrentHashMap由于同步的HashMap;

      b)ConcurrentSkipListMap通常优于同步的TreeMap;

    5)当期望的读数和遍历远远大于列表的更新数时,CopyOnWriteArrayList优于同步的ArrayList。

    CopyOnWriteArrayList的用法示例:

    测试ArrayList并发读写:

    package com.dx.juc.test;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class CopyOnWriteTest {
        public static void main(String[] args) {
            new Thread(new MyCopyOnWrite()).start();
        }
    }
    
    class MyCopyOnWrite implements Runnable {
        private static List<String> items = Collections.synchronizedList(new ArrayList<String>());
    
        static {
            items.add("A");
            items.add("B");
            items.add("C");
        }
    
        public void run() {
            for (String item : items) {
                System.out.println(item);
                items.add("D");
            }
        }
    
    }

    在执行时,抛出异常:

    A
    Exception in thread "Thread-0" java.util.ConcurrentModificationException
        at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
        at java.util.ArrayList$Itr.next(ArrayList.java:831)
        at com.dx.juc.test.MyCopyOnWrite.run(CopyOnWriteTest.java:23)
        at java.lang.Thread.run(Thread.java:745)

    如果使用CopyOnWriteArrayList时,并不会抛出异常,原理是每次在写入时,会在底层拷贝一份新的数据,因此如果是写入时性能不高。

    package com.dx.juc.test;
    
    import java.util.Iterator;
    import java.util.concurrent.CopyOnWriteArrayList;
    
    public class CopyOnWriteTest {
        public static void main(String[] args) {
            MyCopyOnWrite myCopyOnWrite = new MyCopyOnWrite();
    
            for (int i = 0; i < 5; i++) {
                new Thread(myCopyOnWrite).start();
            }
        }
    }
    
    class MyCopyOnWrite implements Runnable {
        private static CopyOnWriteArrayList<String> items = new CopyOnWriteArrayList<String>();
    
        static {
            items.add("A");
            items.add("B");
            items.add("C");
        }
    
        public void run() {
            System.out.println(Thread.currentThread().getName() + ":start");
            Iterator<String> iterator = items.iterator();
            while (iterator.hasNext()) {
                System.out.println(Thread.currentThread().getName() + ":" + iterator.next());
                items.add("D");
            }
            System.out.println(Thread.currentThread().getName() + ":end");
        }
    
    }
  • 相关阅读:
    adb 常用命令及操作
    服务器被黑检查命令
    linux总结
    mysql数据库常用操作
    Python字符串所有操作函数
    Python提示信息表示内容
    Linux基础命令wget(如何联网下载?)
    Linux基础命令sz
    Linux基础命令rz
    Linux基础命令find
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/8910740.html
Copyright © 2011-2022 走看看