Java多线程与并发库高级应用-同步集合
ArrayBlockingQueue
LinkedBlockingQueue
数组是连续的一片内存
链表是不连续的一片内存
传统方式下用Collections工具类提供的synchronizedCollection方法来获得同步集合。
java5中提供了如下一些同步集合类:
> 通过看java.util.concurrent包下的介绍可以知道有哪些并发集合
> ConcurrentHashMap 可以进行并发操作的HashMap,并发的HashMap还有 Collections.synchronizedMap(m) ,有了ConcurrentHashMap后,Collections.synchronizedMap(m)不怎么使用了。
>ConcurrentSkipListMap 实现了SortedMap<K,V> ,类似于TreeMap
>ConcurrentSkipListSet 实现了SortedSet, 类似于TreeSet
> CopyOnWriteArrayList
> CopyOnWriteArraySet
传统方式下的Collection在迭代时,不允许对集合进行修改。
使用Iterator对集合进行迭代时不能修改集合
public class CollectionModifyExceptionTest {
public static void main(String[] args) {
List<String> strs = new ArrayList<>();
strs.add("aaa");
strs.add("bbb");
strs.add("ccc");
Iterator iterator = strs.iterator();
while(iterator.hasNext()){
System.out.println(".....");
String value = (String)iterator.next();
if("aaa".equals(value)){
strs.remove(value);
}else{
System.out.println(value);
}
}
}
}
以上代码在遍历集合时,对集合进行修改,会抛出异常
Exception in thread "main" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at com.java.thread.CollectionModifyExceptionTest.main(CollectionModifyExceptionTest.java:17)
异常抛在这一句
String value = (String)iterator.next();
/**
* An optimized version of AbstractList.Itr
*/
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount; public boolean hasNext() { //
return cursor != size;
} @SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
cursor = i + 1;
return (E) elementData[lastRet = i];
} public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification(); try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
} final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();//此处抛异常
}
}
然而在将"aaa" 改成"bbb"时,却没有抛出异常
因为在遍历到 bbb 时,cursor为1(0,1,2),将 bbb 移除后size为2 进行下次遍历是cursor为 2
所以hasNext()返回的为false 就不会进入循环。
要解决这个问题,可以使用 CopyOnWriteArrayList 在写的时候有一份拷贝,
public static void main(String[] args) {
List<String> strs = new CopyOnWriteArrayList();
strs.add("aaa");
strs.add("bbb");
strs.add("ccc");
Iterator iterator = strs.iterator();
while(iterator.hasNext()){
System.out.println(".....");
String value = (String)iterator.next();
if("aaa".equals(value)){
strs.remove(value);
}else{
System.out.println(value);
}
}
}
Java多线程与并发库高级应用-同步集合的更多相关文章
- Java多线程与并发库高级应用-java5线程并发库
java5 中的线程并发库 主要在java.util.concurrent包中 还有 java.util.concurrent.atomic子包和java.util.concurrent.lock子包 ...
- Java多线程与并发库高级应用-传统线程同步通信技术
面试题: 子线程循环10次,接着主线程循环100次,接着又回到子线程循环10次,接着又 主线程循环100次,如此循环50次,请写出程序 /** * 子线程循环10次,接着主线程循环100次,接着又回到 ...
- Java多线程与并发库高级应用-工具类介绍
java.util.concurrent.Lock 1.Lock比传统线程模型中的synchronized方式更加面向对象,与生活中的锁类似,锁本身也应该是一个对象.两个线程执行的代码片段要实现同步互 ...
- Java多线程与并发库高级应用-传统线程机制回顾
1.传统线程机制的回顾 1.1创建线程的两种传统方式 在Thread子类覆盖的run方法中编写运行代码 // 1.使用子类,把代码放到子类的run()中运行 Thread thread = new T ...
- Java多线程与并发库高级应用-面试题
第一题:现有的程序代码模拟产生了16个日志对象,并且需要运行16秒才能打印完这些日志,请在程序中增加4个线程去调用parseLog()方法来分头打印这16个日志对象,程序只需要运行4秒即可打印完这些日 ...
- Java多线程与并发库高级应用-可阻塞的队列
ArrayBlockQueue 可阻塞的队列 > 队列包含固定长度的队列和不固定长度的队列. > ArrayBlockQueue > 看BlockingQueue类的帮助文档,其中有 ...
- Java多线程与并发库高级应用-Callable与Future的应用
Callable这种任务可以返回结果,返回的结果可以由Future去拿 >Future取得的结果类型和Callable返回的结果类型必须一致,这是通过泛型来实现的. >Completion ...
- Java多线程与并发库高级应用-线程池
线程池 线程池的思想 线程池的概念与Executors类的应用 > 创建固定大小的线程池 > 创建缓存线程池 > 创建单一线程池(如何实现线程死掉后重新启动?) 关闭线程池 > ...
- Java多线程与并发库高级应用-传统线程互斥技术
线程安全问题: 多个线程操作同一份数据的时候,有可能会出现线程安全问题.可以用银行转账来解释. 模拟线程安全问题 /** * 启动两个线程分别打印两个名字,名字按照字符一个一个打印 * * @aut ...
随机推荐
- angularjs之$timeout指令
angular.js的$timeout指令对window.setTimeout做了一个封装,它的返回值是一个promise对象.当定义的时间到了以后,这个promise对象就会被resolve,回调函 ...
- linux运维中的命令梳理(四)
----------管理命令---------- ps命令:查看进程 要对系统中进程进行监测控制,查看状态,内存,CPU的使用情况,使用命令:/bin/ps (1) ps :是显示瞬间进程的状态,并不 ...
- X200s,Debian 8(Jessie) 安装流水帐
1. U盘启动安装 a. 因为无线网卡驱动是non-free,需要另外下载,对应X200s,文件是iwlwifi-5000-5.ucode,下完放到安装U盘的根目录下,安装时就不会再提示而是直接安装 ...
- PAT 1019. 数字黑洞 (20)
给定任一个各位数字不完全相同的4位正整数,如果我们先把4个数字按非递增排序,再按非递减排序,然后用第1个数字减第2个数字,将得到一个新的数字.一直重复这样做,我们很快会停在有"数字黑洞&qu ...
- PL/SQL Transaction Control
PL/SQL 基础 ( 下 ) 1. PL/SQL中的 SQL语句 - END语句与COMMIT等内容,没有任何关系. - PL/SQL does not directly support dat ...
- f2fs中node page的lock_page
[都是思想片段, 待好好整理] node page的lock_page首先是为了改变page的状态:set_page_dirty, 还有set_nid操作时也会设置父节点的nid, 但是这样设置nod ...
- 043医疗项目-模块四:采购单模块—采购单明细查询(Dao,Service,Action三层)
前一篇文章我们做的是在医院的角度上添加在采购单里面添加药品.这一篇文章是查看我们添加的采购单信息. 我们先看一下要实现的效果:当: 按下确认添加时,会在这里 显示出刚才添加的数据. 好,我们就来做这个 ...
- 推薦使用 Microsoft Anti-Cross Site Scripting Library v3.1
原文链接:http://blog.miniasp.com/post/2009/09/27/Recommand-Microsoft-Anti-XSS-Library-V31.aspx 雖然我之前已經寫過 ...
- Android智能指针sp wp详解
研究Android的时候,经常会遇到sp.wp的东西,网上一搜,原来是android封装了c++中对象回收机制.说明:1. 如果一个类想使用智能指针,那么必须满足下面两个条件: a. 该类是虚基 ...
- Linux共享库 socket辅助方法
//sockhelp.h#ifndef _vx #define _vx #ifdef __cplusplus extern "C" { #endif /** * readn - 读 ...