SAN_YUN 2009-04-09 13:28
浏览 603
已采纳

多线程操作导致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 17: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 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站
  • ¥50 成都蓉城足球俱乐部小程序抢票
  • ¥15 yolov7训练自己的数据集
  • ¥15 esp8266与51单片机连接问题(标签-单片机|关键词-串口)(相关搜索:51单片机|单片机|测试代码)
  • ¥15 电力市场出清matlab yalmip kkt 双层优化问题
  • ¥30 ros小车路径规划实现不了,如何解决?(操作系统-ubuntu)