List在遍历的时候是不能进行添加和删除的。
目前的问题是,有两个线程,都是每隔一定实现循环一次。。
其中一个是对list的遍历,另一个是对list的添加和删除。
在某些时候会出现同时遍历和添加或删除,会抛出java.util.ConcurrentModificationException异常。
在保证两线程功能的情况下如何解决这类问题??
------解决方案--------------------------------------------------------
多线程对list的数据结构进行更改时应对整个list进行锁定:
synchronized (list) {
// 添加或者删除都放里面
}
否则即使用线程安全的Vector也会抛出java.util.ConcurrentModificationException异常。
------解决方案--------------------------------------------------------
可以用Iterator的remove()方法,将需要添加或者删除的list放到Iterator :
- Java code
public void setReparation( Reparation reparation ) { boolean flag = false; for (Iterator it = this.reparations.iterator();it.hasNext();){ //reparations为Collection Reparation repa = (Reparation)it.next(); if (repa.getId() == reparation.getId()){ it.remove(); flag = true; break; } } if(flag){ this.reparations.add(reparation); } }
------解决方案--------------------------------------------------------
如果是读比较频繁,写比较少的话,可以用CopyOnWriteArrayList
这个是ArrayList并发版本
遍历的时候对list的添加和删除不需要锁
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
可以定义一个标记 sign,当某个线程启动前先检查这个标记,类似于操作系统的管理线程那样。
------解决方案--------------------------------------------------------
考虑考虑ConcurrentLinkedQueue,虽然它是个queue
------解决方案--------------------------------------------------------
------解决方案--------------------------------------------------------
不就是线程同步问题么
------解决方案--------------------------------------------------------
- Java code
import java.util.Iterator;import java.util.LinkedList;public class test{ public static void main(String[] args) { LinkedList<String> test = new LinkedList<String>(); for (int i = 0; i < 10000000; i++) test.add("aaa"); Add cadd = new Add(test); Traverse ctra = new Traverse(test); final Thread add = new Thread(cadd); final Thread tra = new Thread(ctra); add.start(); tra.start(); }}class Add implements Runnable{ LinkedList<String> test; public Add(LinkedList<String> test) { this.test = test; } public void run() { while (true) { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (test) { for (Iterator<String> it = test.iterator(); it.hasNext();) { String tmp = (String) it.next(); it.remove(); } } } }}class Traverse implements Runnable{ LinkedList<String> test; public Traverse(LinkedList<String> test) { this.test = test; } public void run() { while (true) { try { Thread.sleep(30); } catch (InterruptedException e) { e.printStackTrace(); } synchronized (test) { for (String str : test) { if (str.isEmpty()) continue; } } } }}