SAN_YUN 2009-04-09 05:28
浏览 605
已采纳

多线程操作导致list报NoSuchElementException

为什么我用两个线程操作一个list,一个不断的删除,一个不断的添加。
会导致
Exception in thread "Thread-0" java.util.NoSuchElementException
at java.util.LinkedList.remove(LinkedList.java:788)
at java.util.LinkedList.removeFirst(LinkedList.java:134)
at SynlistTest.remove(SynlistTest.java:10)
at SynlistTest$1.run(SynlistTest.java:27)
at java.lang.Thread.run(Thread.java:619)
[code="java"]
public class SynlistTest {

LinkedList<String> items = new LinkedList<String>();

public String remove() {

    if (!items.isEmpty()) {
         return items.removeFirst();
     }
    return null;
}

public void add(String item) {

    items.add(item);
}


public void test() {

    Runnable thread1 = new Runnable() {

        public void run() {
            while (true) {
                remove();
            }
        }
    };

    Runnable thread2 = new Runnable() {

        public void run() {
            while (true) {
                add("sanyun");
            }
        }
    };

    new Thread(thread1).start();
    new Thread(thread2).start();
}

public static void main(String[] args) {

    new SynlistTest().test();
}

}
[/code]

展开全部

  • 写回答

3条回答 默认 最新

  • liwenzhengloveliuli 2009-04-13 09:12
    关注

    我给你的类稍微做了修改
    public class SynlistTest {

    List items = Collections.synchronizedList(new LinkedList());
    // LinkedList items = new LinkedList();

     public String remove() {  
    
         if (!items.isEmpty()) {  
             //使用索引代替removefirst();
              return   items.remove(0); 
          }  
         return null;  
     } 
    

    主要的问题是LinkedList是非线程安全的,如果多个线程同时访问列表,而其中至少一个线程从结构上修改了该列表,则它必须 保持外部同步。我帮你修改了是基于LIST的,如果也可以使用下面的方式基于linklist的线程安全的访问。

    public class SynlistTest {

     LinkedList<String> items = new LinkedList<String>(); 
    
     String flag="110";
     public  String remove() {  
         synchronized(flag){
         if (!items.isEmpty()) {  
             System.out.println("remove.......");
              return items.removeFirst();  
          }  
         return null;  
     }  }
    
     public void add(String item) {  
         synchronized(flag){
             System.out.println("add.......");
         items.add(item);  
         }
     } 
    

    两个线程共享这个判断标志flag,当第一个线程执行add操作的时候将flag的标志位修改此时如果第二个线程来访问标志位,发现不对正在被使用 就不会执行操作。所以就不会出现同时add和move的情况,确保了同步。

    展开全部

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)
编辑
预览

报告相同问题?

悬赏问题

  • ¥15 WSL上下载的joern在windows怎么用?
  • ¥17 MC9S12XS128单片机开发板实验
  • ¥15 jetson nano4GB
  • ¥15 电脑回复出厂设置,重装过程报错提示,求解决方案Windows 无法分析或处理无人参与应答文件 [C:\WINDOWS\Panther\unattend.xml,如何解决?
  • ¥15 进入lighttools中的UDOP编辑器的方法
  • ¥15 求Gen6d训练数据集
  • ¥20 liunx中winscp中可以登入ftp,但是不能登入sftp,如何解决
  • ¥15 lighttools的光学属性自定义的用法流程
  • ¥15 uni-app动态修改推荐页标题时报错
  • ¥15 图片是GET请求,后面是图片的id,Glide如何缓存?
手机看
程序员都在用的中文IT技术交流社区

程序员都在用的中文IT技术交流社区

专业的中文 IT 技术社区,与千万技术人共成长

专业的中文 IT 技术社区,与千万技术人共成长

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

关注【CSDN】视频号,行业资讯、技术分享精彩不断,直播好礼送不停!

客服 返回
顶部