日期:2014-05-20  浏览次数:20918 次

不同线程同时读写同一内容时的问题
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的添加和删除不需要锁
------解决方案--------------------
探讨

如果是读比较频繁,写比较少的话,可以用CopyOnWriteArrayList
这个是ArrayList并发版本
遍历的时候对list的添加和删除不需要锁

------解决方案--------------------
可以定义一个标记 sign,当某个线程启动前先检查这个标记,类似于操作系统的管理线程那样。
------解决方案--------------------
考虑考虑ConcurrentLinkedQueue,虽然它是个queue
------解决方案--------------------
探讨

引用:

多线程对list的数据结构进行更改时应对整个list进行锁定:
synchronized (list) {
// 添加或者删除都放里面
}
否则即使用线程安全的Vector也会抛出java.util.ConcurrentModificationException异常。


话说 synchronized这东西是干嘛的。。 我看了半天也没看懂

------解决方案--------------------
不就是线程同步问题么
------解决方案--------------------
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;
                }
            }
        }
    }
}