知识大全 多线程中使用Java集合类
Posted 元素
篇首语:追风赶月莫停留,平芜尽处是春山。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 多线程中使用Java集合类相关的知识,希望对你有一定的参考价值。
多线程中使用Java集合类 以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!
Java集合类中 某个线程在 Collection 上进行迭代时 通常不允许另一个线性修改该 Collection 通常在这些情况下 迭代的结果是不确定的 如果检测到这种行为 一些迭代器实现(包括 JRE 提供的所有通用 collection 实现)可能选择抛出此异常 执行该操作的迭代器称为快速失败 迭代器 因为迭代器很快就完全失败 而不会冒着在将来某个时间任意发生不确定行为的风险
因此 当一个线程试图ArrayList的数据的时候 另一个线程对ArrayList在进行迭代的 会出错 抛出ConcurrentModificationException
比如下面的代码
final List<String> tickets = new ArrayList<String>();
for (int i = ; i < ; i++)
tickets add( ticket NO + i);
System out println( start );
for (int i = ; i < ; i++)
Thread salethread = new Thread()
public void run()
while (tickets size() > )
tickets remove( );
System out println(Thread currentThread() getId()+ Remove );
;
salethread start();
System out println( start );
new Thread()
public void run()
for (String s : tickets)
System out println(s);
start();
上述程序运行后 会在某处抛出异常
java util ConcurrentModificationException
at java util ArrayList$Itr checkForComodification(Unknown Source)
at java util ArrayList$Itr next(Unknown Source)
at mytest mytestpkg Tj$ run(Tj java: )
Vector是线程同步的 那么把ArrayList改成Vector是不是就对了呢?
答案是否定的 事实上 无论是ArrayList还是Vector 只要是实现Collection接口的 都要遵循fail fast的检测机制 即在迭代是时候 不能修改集合的元素 一旦发现违法这个规定就会抛出异常
事实上 Vector相对于ArrayList的线程同步 体现在对集合元素是否脏读上 即ArrayList允许脏读 而Vector特殊的机制 不会出现脏读 但是效率会很差
举个例子 一个集合 有 个线程从该集合中删除元素 那么每个元素只可能由一个线程删除掉 不可能会出现一个元素被多个线程删除的情况
比如下面的代码
final List<String> tickets = new ArrayList<String>();
for (int i = ; i < ; i++)
tickets add( ticket NO + i);
System out println( start );
for (int i = ; i < ; i++)
Thread salethread = new Thread()
public void run()
while (true)
if(tickets size()> )
System out println(Thread currentThread() getId()+ tickets remove( ));
else
break;
;
salethread start();
for循环构造 个线程删除同一个集合中的数据 理论上只能删除 次 但是运行完发现 输出的删除次数 次 其中很多数据都是被多个线程删除 比如下面的输出片段
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
ticket NO
可以看到 都被多个线程删除 这事实上就是出现了脏读 解决的办法就是加锁 使得同一时刻只有 个线程对ArrayList做操作
修改代码 synchronized关键字 让得到锁对象的线程才能运行 这样确保同一时刻只有一个线程操作集合
final List<String> tickets = new ArrayList<String>();
for (int i = ; i < ; i++)
tickets add( ticket NO + i);
System out println( start );
final Object lock=new Object();
for (int i = ; i < ; i++)
Thread salethread = new Thread()
public void run()
while (true)
synchronized(lock)
if(tickets size()> )
System out println(Thread currentThread() getId()+ tickets remove( ));
else
break;
;
salethread start();
这样得到的结果就是准确的了
当然 不使用synchronized关键字 而直接使用vector或者Collections synchronizedList 也是同样效果
final List<String> tickets =java util Collections synchronizedList(new ArrayList<String>());
final List<String> tickets =new Vector<String>();
cha138/Article/program/Java/gj/201311/27405相关参考