List线程不安全导致,你想要得到什么样的效果

解决方案 »

  1.   

     觉得是 list.remove(i); 的问题,你可以先注释掉看程序可以不   
      

  2.   

    此处其实只有一个image 也只有一个list 三个线程都要用list,只需要在for之前加上锁 synchronized (list) {}
      

  3.   

    List在遍历的时候不能remove,这个你可以百度一下
      

  4.   

    有一个类弥补了 list遍历时不能remove的缺点,好像是 ListIterator这个类
      

  5.   

    synchronized好像可以加在类前面。
      

  6.   

    是remove的问题,但是并非是指通常意义的遍历时Remove报错。
    所谓的遍历时报错,是指先吧List装到一个Iterator中, 然后这边用Iterator.next遍历,那边用List.remove时出错。另外,我觉得LZ的遍历代码和Remove代码有很大的问题 -- 一般来说,我觉得这个遍历时希望各个线程能尽可能快的抓List的第1个img,如果抓到了就把它排除出去。不过即便是单线程,LZ的代码也是达不到这个目的的。
    假设有List中有10个img,分别是000,001,002,...,009,通常,对于单线程来讲,希望它的输出结果就是000,001,002,...,009.
    不过模拟一下就可以发现,第一个输出元素是item[0],即000不假,不过此后由于Remove语句,所以List变成了[001,002,003,...,009],然后i=1,结果下一个输出是002。
    再接下去是004,006,008此外,线程的 判断数据存在+显示数据+删除数据 应当加上同步锁,否则当判断数据时有数据存在,当显示数据时系统发现该数据已经被其它线程删除了,自然会报IndexOutofRange错误。是我的话,线程代码可能会改成  public void run() {
             List<String> list = image.getUrls();
             for (; list.size()>0;) {
             synchronized(this){
                 if (list.size() > 0) {
                     System.out.println(list.get(0) + "---" + Thread.currentThread().getName());
                     list.remove(0);
                 }
             }
             }
         }
      

  7.   


    public class ImageDFile extends Thread {
        public Image image;
        public ImageDFile(Image image) {
            this.image = image;
        }    @Override
        public void run() {
         synchronized (image) { // 在此处添加synchronized关键字即可
         List<String> list = image.getUrls();
                for (int i = 0; i < list.size(); i++) {
                    if (list.size() > 0) {
                        System.out.println(list.get(i) + "---" + Thread.currentThread().getName());
                        list.remove(i);
                    }
                }
    }
            
        }
    }原因:试想一下,并发问题,一般由于多线程访问共享资源(未加任何同步机制)引起的。多个线程同时,遍历同一个List,且删除元素,只要保证同一时刻只有一个线程对List进行操作即可。
      

  8.   

    原因就是遍历的同时,又删除了元素!这是典型的集合并发问题1.你可以将要删除的元素记录下来,遍历完之后再删除。
    2.你可以使用并发库中的线程安全的集合。Concurrentxxx
    3.使用老的一个方法包一层,返回回来的就是安全的集合。有点忘记了。那个叫什么来Synchrinize打头的。