JUC学习之同步容器类ConcurrentHashMap

本文是看视频的笔记,若有错误请指出,谢谢!

jdk1.5之后添加了ConcurrentHashMap类,其底层是CAS算法实现的,采用的是“锁分段”机制,有个concurrentLevel分段级别,默认的级别为16,也就是说默认有16个分段,每个分段中也有一个默认长度为16的表,表中的每个单位由链表组成。

每个段都是独立地锁,当多个线程并发访问时,可以并行进行操作,效率高了并且线程安全。

《JUC学习之同步容器类ConcurrentHashMap》

在这个包中还提供了设计用于多线程上下文的collection实现:

ConcurrentHashMap,ConcurrentSkipListMap,ConcurrentSkipListSet,CopyOnWriterArrayList和CopyOnWriterArraySet。当期望许多线程访问一个给定的collection时,ConcurrentHashMap通常情况下优于同步的HashMap,ConcurrentSkipListMap通常优于同步的TreeMap。当期望的读数和便利远远大于列表的更新数量时,CopyOnWriterArrayList通常优于同步的ArrayList。

拿CopyOnWriterArrayList举例

public class TestCopyOnWriterArrayList {

    public static void main(String[] args){

        HelloThread helloThread = new HelloThread();
        for(int i = 0;i< 10;i++){
            new Thread(helloThread).start();
        }
    }
}

class HelloThread implements Runnable{

    private static List<String> list = Collections.synchronizedList(new ArrayList<>());
    
    static{
        list.add("AA");
        list.add("BB");
        list.add("CC");
    }
    @Override
    public void run() {
        Iterator<String> it = list.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
            list.add("AA");
        }

    }
}

运行结果:

"C:\Program Files\Java\jdk1.8.0_144\bin\java" -javaagent:D:\java\IDEA\lib\idea_rt.jar=52042:D:\java\IDEA\bin -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_144\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_144\jre\lib\rt.jar;D:\phpstudy\WWW\xioajinshuju_1\target\test-classes;D:\phpstudy\WWW\xioajinshuju_1\target\classes;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter\1.5.6.RELEASE\spring-boot-starter-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot\1.5.6.RELEASE\spring-boot-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-context\4.3.10.RELEASE\spring-context-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-autoconfigure\1.5.6.RELEASE\spring-boot-autoconfigure-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-core\4.3.10.RELEASE\spring-core-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\yaml\snakeyaml\1.17\snakeyaml-1.17.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-devtools\1.5.6.RELEASE\spring-boot-devtools-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-log4j2\1.5.6.RELEASE\spring-boot-starter-log4j2-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-slf4j-impl\2.7\log4j-slf4j-impl-2.7.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-api\2.7\log4j-api-2.7.jar;C:\Users\Administrator\.m2\repository\org\apache\logging\log4j\log4j-core\2.7\log4j-core-2.7.jar;C:\Users\Administrator\.m2\repository\org\slf4j\jcl-over-slf4j\1.7.25\jcl-over-slf4j-1.7.25.jar;C:\Users\Administrator\.m2\repository\org\slf4j\jul-to-slf4j\1.7.25\jul-to-slf4j-1.7.25.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-web\1.5.6.RELEASE\spring-boot-starter-web-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-tomcat\1.5.6.RELEASE\spring-boot-starter-tomcat-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-core\8.5.16\tomcat-embed-core-8.5.16.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-el\8.5.16\tomcat-embed-el-8.5.16.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\embed\tomcat-embed-websocket\8.5.16\tomcat-embed-websocket-8.5.16.jar;C:\Users\Administrator\.m2\repository\org\hibernate\hibernate-validator\5.3.5.Final\hibernate-validator-5.3.5.Final.jar;C:\Users\Administrator\.m2\repository\javax\validation\validation-api\1.1.0.Final\validation-api-1.1.0.Final.jar;C:\Users\Administrator\.m2\repository\org\jboss\logging\jboss-logging\3.3.1.Final\jboss-logging-3.3.1.Final.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\classmate\1.3.3\classmate-1.3.3.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.8.9\jackson-databind-2.8.9.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.8.0\jackson-annotations-2.8.0.jar;C:\Users\Administrator\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.8.9\jackson-core-2.8.9.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-web\4.3.10.RELEASE\spring-web-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-beans\4.3.10.RELEASE\spring-beans-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-webmvc\4.3.10.RELEASE\spring-webmvc-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-expression\4.3.10.RELEASE\spring-expression-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-test\1.5.6.RELEASE\spring-boot-starter-test-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test\1.5.6.RELEASE\spring-boot-test-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-test-autoconfigure\1.5.6.RELEASE\spring-boot-test-autoconfigure-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\com\jayway\jsonpath\json-path\2.2.0\json-path-2.2.0.jar;C:\Users\Administrator\.m2\repository\net\minidev\json-smart\2.2.1\json-smart-2.2.1.jar;C:\Users\Administrator\.m2\repository\net\minidev\accessors-smart\1.1\accessors-smart-1.1.jar;C:\Users\Administrator\.m2\repository\org\ow2\asm\asm\5.0.3\asm-5.0.3.jar;C:\Users\Administrator\.m2\repository\junit\junit\4.12\junit-4.12.jar;C:\Users\Administrator\.m2\repository\org\assertj\assertj-core\2.6.0\assertj-core-2.6.0.jar;C:\Users\Administrator\.m2\repository\org\mockito\mockito-core\1.10.19\mockito-core-1.10.19.jar;C:\Users\Administrator\.m2\repository\org\objenesis\objenesis\2.1\objenesis-2.1.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-core\1.3\hamcrest-core-1.3.jar;C:\Users\Administrator\.m2\repository\org\hamcrest\hamcrest-library\1.3\hamcrest-library-1.3.jar;C:\Users\Administrator\.m2\repository\org\skyscreamer\jsonassert\1.4.0\jsonassert-1.4.0.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-test\4.3.10.RELEASE\spring-test-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\session\spring-session-data-redis\1.3.1.RELEASE\spring-session-data-redis-1.3.1.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\apache\commons\commons-pool2\2.4.2\commons-pool2-2.4.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\data\spring-data-redis\1.8.6.RELEASE\spring-data-redis-1.8.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\data\spring-data-keyvalue\1.2.6.RELEASE\spring-data-keyvalue-1.2.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-tx\4.3.10.RELEASE\spring-tx-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-oxm\4.3.10.RELEASE\spring-oxm-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-context-support\4.3.10.RELEASE\spring-context-support-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\session\spring-session\1.3.1.RELEASE\spring-session-1.3.1.RELEASE.jar;C:\Users\Administrator\.m2\repository\redis\clients\jedis\2.9.0\jedis-2.9.0.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-data-jpa\1.5.6.RELEASE\spring-boot-starter-data-jpa-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-aop\1.5.6.RELEASE\spring-boot-starter-aop-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\aspectj\aspectjweaver\1.8.10\aspectjweaver-1.8.10.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-jdbc\1.5.6.RELEASE\spring-boot-starter-jdbc-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\tomcat-jdbc\8.5.16\tomcat-jdbc-8.5.16.jar;C:\Users\Administrator\.m2\repository\org\apache\tomcat\tomcat-juli\8.5.16\tomcat-juli-8.5.16.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-jdbc\4.3.10.RELEASE\spring-jdbc-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\hibernate\hibernate-core\5.0.12.Final\hibernate-core-5.0.12.Final.jar;C:\Users\Administrator\.m2\repository\org\hibernate\javax\persistence\hibernate-jpa-2.1-api\1.0.0.Final\hibernate-jpa-2.1-api-1.0.0.Final.jar;C:\Users\Administrator\.m2\repository\org\javassist\javassist\3.21.0-GA\javassist-3.21.0-GA.jar;C:\Users\Administrator\.m2\repository\antlr\antlr\2.7.7\antlr-2.7.7.jar;C:\Users\Administrator\.m2\repository\org\jboss\jandex\2.0.0.Final\jandex-2.0.0.Final.jar;C:\Users\Administrator\.m2\repository\dom4j\dom4j\1.6.1\dom4j-1.6.1.jar;C:\Users\Administrator\.m2\repository\org\hibernate\common\hibernate-commons-annotations\5.0.1.Final\hibernate-commons-annotations-5.0.1.Final.jar;C:\Users\Administrator\.m2\repository\org\hibernate\hibernate-entitymanager\5.0.12.Final\hibernate-entitymanager-5.0.12.Final.jar;C:\Users\Administrator\.m2\repository\javax\transaction\javax.transaction-api\1.2\javax.transaction-api-1.2.jar;C:\Users\Administrator\.m2\repository\org\springframework\data\spring-data-jpa\1.11.6.RELEASE\spring-data-jpa-1.11.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\data\spring-data-commons\1.13.6.RELEASE\spring-data-commons-1.13.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-orm\4.3.10.RELEASE\spring-orm-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aspects\4.3.10.RELEASE\spring-aspects-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\mysql\mysql-connector-java\5.1.43\mysql-connector-java-5.1.43.jar;C:\Users\Administrator\.m2\repository\com\alibaba\druid\1.0.18\druid-1.0.18.jar;C:\Program Files\Java\jdk1.8.0_144\lib\jconsole.jar;C:\Program Files\Java\jdk1.8.0_144\lib\tools.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-security\1.5.6.RELEASE\spring-boot-starter-security-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\spring-aop\4.3.10.RELEASE\spring-aop-4.3.10.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\security\spring-security-config\4.2.3.RELEASE\spring-security-config-4.2.3.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\security\spring-security-core\4.2.3.RELEASE\spring-security-core-4.2.3.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\springframework\security\spring-security-web\4.2.3.RELEASE\spring-security-web-4.2.3.RELEASE.jar;C:\Users\Administrator\.m2\repository\com\aliyun\oss\aliyun-sdk-oss\2.7.0\aliyun-sdk-oss-2.7.0.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpclient\4.5.3\httpclient-4.5.3.jar;C:\Users\Administrator\.m2\repository\org\apache\httpcomponents\httpcore\4.4.6\httpcore-4.4.6.jar;C:\Users\Administrator\.m2\repository\commons-codec\commons-codec\1.10\commons-codec-1.10.jar;C:\Users\Administrator\.m2\repository\org\jdom\jdom\1.1\jdom-1.1.jar;C:\Users\Administrator\.m2\repository\net\sf\json-lib\json-lib\2.4\json-lib-2.4-jdk15.jar;C:\Users\Administrator\.m2\repository\commons-beanutils\commons-beanutils\1.9.3\commons-beanutils-1.9.3.jar;C:\Users\Administrator\.m2\repository\commons-collections\commons-collections\3.2.2\commons-collections-3.2.2.jar;C:\Users\Administrator\.m2\repository\commons-lang\commons-lang\2.5\commons-lang-2.5.jar;C:\Users\Administrator\.m2\repository\commons-logging\commons-logging\1.1.1\commons-logging-1.1.1.jar;C:\Users\Administrator\.m2\repository\net\sf\ezmorph\ezmorph\1.0.6\ezmorph-1.0.6.jar;C:\Users\Administrator\.m2\repository\org\springframework\boot\spring-boot-starter-thymeleaf\1.5.6.RELEASE\spring-boot-starter-thymeleaf-1.5.6.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\thymeleaf\thymeleaf-spring4\2.1.5.RELEASE\thymeleaf-spring4-2.1.5.RELEASE.jar;C:\Users\Administrator\.m2\repository\org\thymeleaf\thymeleaf\2.1.5.RELEASE\thymeleaf-2.1.5.RELEASE.jar;C:\Users\Administrator\.m2\repository\ognl\ognl\3.0.8\ognl-3.0.8.jar;C:\Users\Administrator\.m2\repository\org\unbescape\unbescape\1.1.0.RELEASE\unbescape-1.1.0.RELEASE.jar;C:\Users\Administrator\.m2\repository\nz\net\ultraq\thymeleaf\thymeleaf-layout-dialect\1.4.0\thymeleaf-layout-dialect-1.4.0.jar;C:\Users\Administrator\.m2\repository\org\codehaus\groovy\groovy\2.4.12\groovy-2.4.12.jar;C:\Users\Administrator\.m2\repository\net\sourceforge\nekohtml\nekohtml\1.9.22\nekohtml-1.9.22.jar;C:\Users\Administrator\.m2\repository\xerces\xercesImpl\2.11.0\xercesImpl-2.11.0.jar;C:\Users\Administrator\.m2\repository\xml-apis\xml-apis\1.4.01\xml-apis-1.4.01.jar;C:\Users\Administrator\.m2\repository\org\quartz-scheduler\quartz\2.3.0\quartz-2.3.0.jar;C:\Users\Administrator\.m2\repository\com\mchange\c3p0\0.9.5.2\c3p0-0.9.5.2.jar;C:\Users\Administrator\.m2\repository\com\mchange\mchange-commons-java\0.2.11\mchange-commons-java-0.2.11.jar;C:\Users\Administrator\.m2\repository\com\zaxxer\HikariCP-java6\2.3.13\HikariCP-java6-2.3.13.jar;C:\Users\Administrator\.m2\repository\org\slf4j\slf4j-api\1.7.25\slf4j-api-1.7.25.jar;C:\Users\Administrator\.m2\repository\com\aliyun\aliyun-java-sdk-dysmsapi\1.1.0\aliyun-java-sdk-dysmsapi-1.1.0.jar;C:\Users\Administrator\.m2\repository\com\aliyun\aliyun-java-sdk-core\3.5.1\aliyun-java-sdk-core-3.5.1.jar;C:\Users\Administrator\.m2\repository\org\json\json\20140107\json-20140107.jar;C:\Users\Administrator\.m2\repository\com\alibaba\fastjson\1.2.15\fastjson-1.2.15.jar;C:\Users\Administrator\.m2\repository\com\baidu\aip\java-sdk\4.1.1\java-sdk-4.1.1.jar;C:\Users\Administrator\.m2\repository\log4j\log4j\1.2.17\log4j-1.2.17.jar;C:\Users\Administrator\.m2\repository\com\itextpdf\itext-asian\5.2.0\itext-asian-5.2.0.jar;C:\Users\Administrator\.m2\repository\com\itextpdf\itextpdf\5.5.12\itextpdf-5.5.12.jar;C:\Users\Administrator\.m2\repository\com\itextpdf\tool\xmlworker\5.5.12\xmlworker-5.5.12.jar;C:\Users\Administrator\.m2\repository\org\xhtmlrenderer\flying-saucer-pdf\9.0.3\flying-saucer-pdf-9.0.3.jar;C:\Users\Administrator\.m2\repository\com\lowagie\itext\2.1.7\itext-2.1.7.jar;C:\Users\Administrator\.m2\repository\bouncycastle\bcmail-jdk14\138\bcmail-jdk14-138.jar;C:\Users\Administrator\.m2\repository\bouncycastle\bcprov-jdk14\138\bcprov-jdk14-138.jar;C:\Users\Administrator\.m2\repository\org\bouncycastle\bctsp-jdk14\1.38\bctsp-jdk14-1.38.jar;C:\Users\Administrator\.m2\repository\org\bouncycastle\bcprov-jdk14\1.38\bcprov-jdk14-1.38.jar;C:\Users\Administrator\.m2\repository\org\bouncycastle\bcmail-jdk14\1.38\bcmail-jdk14-1.38.jar;C:\Users\Administrator\.m2\repository\org\xhtmlrenderer\flying-saucer-core\9.0.3\flying-saucer-core-9.0.3.jar;C:\Users\Administrator\.m2\repository\org\freemarker\freemarker\2.3.26-incubating\freemarker-2.3.26-incubating.jar;C:\Users\Administrator\.m2\repository\com\google\guava\guava\22.0\guava-22.0.jar;C:\Users\Administrator\.m2\repository\com\google\code\findbugs\jsr305\1.3.9\jsr305-1.3.9.jar;C:\Users\Administrator\.m2\repository\com\google\errorprone\error_prone_annotations\2.0.18\error_prone_annotations-2.0.18.jar;C:\Users\Administrator\.m2\repository\com\google\j2objc\j2objc-annotations\1.1\j2objc-annotations-1.1.jar;C:\Users\Administrator\.m2\repository\org\codehaus\mojo\animal-sniffer-annotations\1.14\animal-sniffer-annotations-1.14.jar" com.shangdao.phoenix.TestCopyOnWriterArrayList
Exception in thread "Thread-0" Exception in thread "Thread-1" Exception in thread "Thread-2" java.util.ConcurrentModificationException
AA
AA
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
AA
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
AA
Exception in thread "Thread-3" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
AA
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
AA
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-4" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-5" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
AA
Exception in thread "Thread-6" java.util.ConcurrentModificationException
AA
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-7" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
AA
	at java.lang.Thread.run(Thread.java:748)
Exception in thread "Thread-8" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)
AA
Exception in thread "Thread-9" java.util.ConcurrentModificationException
	at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:901)
	at java.util.ArrayList$Itr.next(ArrayList.java:851)
	at com.shangdao.phoenix.HelloThread.run(TestCopyOnWriterArrayList.java:37)
	at java.lang.Thread.run(Thread.java:748)

Process finished with exit code 0

运行后会报并发修改异常,主要是因为我们的迭代和修改是对同一个数据源进行操作的,这时我们将ArrayList换成CopyOnWriterArrayList

public class TestCopyOnWriterArrayList {

    public static void main(String[] args){

        HelloThread helloThread = new HelloThread();
        for(int i = 0;i< 10;i++){
            new Thread(helloThread).start();
        }
    }
}

class HelloThread implements Runnable{

//    private static List<String> list = Collections.synchronizedList(new ArrayList<>());

    private static CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>();
    
    static{
        list.add("AA");
        list.add("BB");
        list.add("CC");
    }
    @Override
    public void run() {
        Iterator<String> it = list.iterator();

        while(it.hasNext()){
            System.out.println(it.next());
            list.add("AA");
        }

    }
}

修改之后的运行结果:

《JUC学习之同步容器类ConcurrentHashMap》

从结果可以看出,不会产生并发修改异常,对于CopyOnWriterArrayList,当每次进行写入时,它都会在底层进行复制,复制一个新的列表,然后再进行添加。每次写入时都会进行复制,但是会导致效率低,若添加操作多时,不适合使用,但是适合于并发迭代的场景。

    原文作者:JUC
    原文地址: https://blog.csdn.net/dyt443733328/article/details/79976288
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞