不同线程同时读写同一内容时的问题List在遍历的时候是不能进行添加和删除的。目前的问题是,有两个线程,都是
不同线程同时读写同一内容时的问题
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; } } } }}
