Java 即使在检查后也不会出现任何异常
第118行指向:Java 即使在检查后也不会出现任何异常,java,Java,第118行指向: java.util.NoSuchElementException at java.util.LinkedList.remove(LinkedList.java:788) at java.util.LinkedList.removeFirst(LinkedList.java:134) at java.util.LinkedList.poll(LinkedList.java:470) at com.wtsang02.reu.botnet.networ
java.util.NoSuchElementException
at java.util.LinkedList.remove(LinkedList.java:788)
at java.util.LinkedList.removeFirst(LinkedList.java:134)
at java.util.LinkedList.poll(LinkedList.java:470)
at com.wtsang02.reu.botnet.network.GlobalNetwork$1.run(GlobalNetwork.java:118)
at java.lang.Thread.run(Thread.java:662)
java.lang.NullPointerException
Exception in thread "Thread-299" java.lang.AssertionError
at com.wtsang02.reu.botnet.network.GlobalNetwork$1.run(GlobalNetwork.java:119)
at java.lang.Thread.run(Thread.java:662)
如何解决这个问题?队列是LinkedList的实现,如果这有区别的话。
LinkedList
不是线程安全的,所以如果在多个线程上访问LinkedList
,则需要外部同步。此同步在某个对象上(同步的synchronized
方法只是“在This
上同步”)的简写,并且get和put必须在同一个对象上同步。您在这里肯定是这样做的,因为您为每个智能手机
创建了一个新线程,然后从那里访问该手机的链接列表
如果一个线程在someObject1
上同步时将其放入列表,而另一个线程在someObject2
上同步时读取该列表,则这不算作外部同步——代码仍处于中断状态
即使使用了线程安全集合,如果多个线程同时清空队列,也有可能出现此异常。例如,想象一下:
task=tasks.poll();
您应该使用
BlockingQueue
,如果列表中没有更多元素,则其poll()
方法将返回null
。继续拉,直到得到一个null
,然后断开循环。此方法被声明为已同步。是的。多个智能手机实例是否可能具有相同的队列?或者每个队列对于SmartPhone
实例来说都是唯一的?每个队列都是在每个SmartPhone的构造函数中创建的,每个SmartPhone都是唯一的。我所知道的唯一的另一种方法是推送到队列,但我会确保这一点。但是SmartPhone
s是跨线程共享的吗?这在评论中,但我应该补充一个问题。但是该方法被声明为已同步。除非我读取的代码不正确,否则每个LinkedList
只能由一个线程访问,因为LinkedList
应该是它自己的SmartPhone
所独有的,并且每个线程都有一个唯一的SmartPhone
。@wtsang02不管该方法是不是,因为您正在从该方法中启动一个新线程,而该线程的run
方法是不同步的。即使是这样,它也不会与元素中的任何东西同步。请记住,同步总是在某个监视器上完成的,put和get(包括isEmpty
)都需要在同一个监视器上同步。@DennisMeng每个线程肯定没有一个SmartPhone
,因为就在这个代码片段中,我们看到两个线程可以访问相同的列表。BlockingQue似乎是一个更好的解决方案。我现在就试试。
task=tasks.poll();
thread A: put e into queue1
thread B: queue1.isEmpty()? No, so go on
thread C: queue1.isEmpty()? No, so go on
thread B: queue1.poll() // works
thread C: queue1.poll() // NoSuchElementException