List在遍历的时候是不能进行添加和删除的。目前的问题是,有两个线程,都是每隔一定实现循环一次。。
其中一个是对list的遍历,另一个是对list的添加和删除。在某些时候会出现同时遍历和添加或删除,会抛出java.util.ConcurrentModificationException异常。在保证两线程功能的情况下如何解决这类问题??

解决方案 »

  1.   

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

  2.   

    可以用Iterator的remove()方法,将需要添加或者删除的list放到Iterator :
        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);  
            }  
        }  
      

  3.   

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

  4.   

    CopyOnWriteArrayList并不适用于LZ的情况,1/2的可变操作会极大地降低执行效率(远低于同步),这个只适合数据量较少且读操作远多于写操作的情况,它只适合遍历,不适合变更。
      

  5.   

    可以定义一个标记 sign,当某个线程启动前先检查这个标记,类似于操作系统的管理线程那样。
      

  6.   

    考虑考虑ConcurrentLinkedQueue,虽然它是个queue
      

  7.   


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

  8.   

    import java.util.*;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) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    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) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    for (String str:test) {
    if (str.isEmpty())
    continue;
    }
    }
    }
    }比如这样的情况,就会抛出java.util.ConcurrentModificationException异常在不改变功能的情况下,我该怎么修改
      

  9.   


    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;
                    }
                }
            }
        }
    }