Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
多线程java代码的空指针异常_Java_Multithreading_Nullpointerexception - Fatal编程技术网

多线程java代码的空指针异常

多线程java代码的空指针异常,java,multithreading,nullpointerexception,Java,Multithreading,Nullpointerexception,我对使用SimJava仿真库的Java代码有问题。该库基本上帮助创建可以作为java线程运行的独立实体。我遇到的问题是,我有一个代码段,用作作为线程运行的每个实体的主体。这些实体/线程正在这些线程之间共享一个事件(用于传输ConcurrentLinkedQueue)。我使用concurrentlinkedqueue,因为我在LinkedList并发控制方面有问题。 问题是,如果我运行该模型100次或更少的重复次数,它工作得很好。如果我达到100或更多,我会得到并发队列的空指针异常。下面是有问题的

我对使用SimJava仿真库的Java代码有问题。该库基本上帮助创建可以作为java线程运行的独立实体。我遇到的问题是,我有一个代码段,用作作为线程运行的每个实体的主体。这些实体/线程正在这些线程之间共享一个事件(用于传输ConcurrentLinkedQueue)。我使用concurrentlinkedqueue,因为我在LinkedList并发控制方面有问题。 问题是,如果我运行该模型100次或更少的重复次数,它工作得很好。如果我达到100或更多,我会得到并发队列的空指针异常。下面是有问题的主体的代码段

空指针异常发生在我试图从队列中拉出的行,即使前面的行正在检查队列是空的还是空的。异常是在行中抛出的 “nextNode=dcPath.poll().intValue();”

出于某种原因,轮询调用返回null,并且intValue()应用于null对象。我的问题是,在已经检查队列内容之前,if语句如何实现这一点?如何控制此竞争条件

public void body() { 
  synchronized (this){
  ConcurrentLinkedQueue<Integer> dcPath = new ConcurrentLinkedQueue<Integer> ();    
  int nextNode;
  int distance = 0;
  while (Sim_system.running()) {
    Sim_event e = new Sim_event();
    sim_get_next(e);    // Get the next event
    dcPath = (ConcurrentLinkedQueue<Integer>) e.get_data();
    if ((dcPath != null) && (!dcPath.isEmpty())){
      nextNode = dcPath.poll().intValue(); // THIS LINE IS THROWING NPE Exception
      if ((dcPath != null) && (!dcPath.isEmpty())){
        int outPort = findMatchingOutPort(dcPath.peek().intValue());
        if (outPort != -1){
          sim_schedule(out[outPort], 0.0, 0, dcPath); 
          distance = this.calculateSensorToSensorDistance (out[outPort].get_dest());
        }                 
      }
    }
  }
public void body(){
已同步(此){
ConcurrentLinkedQueue dcPath=新的ConcurrentLinkedQueue();
int nextNode;
整数距离=0;
同时(Sim_system.running()){
Sim_事件e=新Sim_事件();
sim_get_next(e);//获取下一个事件
dcPath=(ConcurrentLinkedQueue)e.get_data();
如果((dcPath!=null)&&(!dcPath.isEmpty()){
nextNode=dcPath.poll().intValue();//此行引发NPE异常
如果((dcPath!=null)&&(!dcPath.isEmpty()){
int outPort=findMatchingOutPort(dcPath.peek().intValue());
如果(输出端口!=-1){
sim_调度(out[outPort],0.0,0,dcPath);
距离=this.calculateSensorToSensorDistance(输出[outPort].get_dest());
}                 
}
}
}

我认为问题在于,当您从e.get_data()检索dc_路径时,另一个线程同时读/写到该队列中。因此,您的代码具有:

if ((dcPath != null) && (!dcPath.isEmpty()) {
同时,dcPath不是空的。但是当执行下一行时,另一个线程会弹出剩余的元素并使队列为空,这就是为什么您会得到
dcPath.poll()
一个空值

要防止出现这种情况,您需要同步dcPath引用,而不是
。如下所示:

if (dcPath != null) {
    synchronized (dcPath) {
        //do something
    }
}

此外,在任何涉及对象读/写的其他线程中,您还需要同步对象,以确保其行为符合预期。

我找到了解决问题的方法,我不会说这是最有效的方法(尤其是在内存管理方面)但它可以满足我的模拟模型和需要运行的实例数的要求。 基本上,我在每个线程实例上创建了ConcurrentLinkedQueue dcPath对象的副本,并在对象移动和移动时创建了该对象。这消除了操作该对象时的争用条件。现在,我可以运行一千多次迭代,而不会引发任何异常,扩展线程可以超过500个实例

if (e.get_data() != null){
       ConcurrentLinkedQueue<Integer> dcPath = new ConcurrentLinkedQueue<Integer>        
                                   ((ConcurrentLinkedQueue<Integer>) e.get_data());
if(如get_data()!=null){
ConcurrentLinkedQueue dcPath=新的ConcurrentLinkedQueue
((ConcurrentLinkedQueue)e.get_data());

哪一行正抛出NPE?请对该行进行注释。由于您使用的是intValue()方法,因此发生了某种取消装箱的情况。dcPath.poll()语句的作用是什么return?返回值可能为null-您正试图将其解除绑定到原语int@Ashish:我的想法完全正确。他在一行上链接太多,在尝试调用返回值之前需要检查返回值。整个问题有点太神秘了。@Ashish dcPath.poll()如果队列为空,将返回队列头或null。他在使用它之前没有检查null。Sheesh。感谢您的响应,您建议的更改确实有帮助,但没有完全解决问题。它基本上扩展了模型运行约200次迭代的能力,但如果我尝试超出此范围,它将抛出错误同一行出现相同的异常。很抱歉,我错过了“dcPath.isEmpty()”。原因仍然是,如果要读取/写入dcPath队列,必须确定它在同步块中是否为空。例如
synchronize(dcPath);if(dcPath!=null&&!dcPath.isEmpty()){//do something}