Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/323.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-LinkedList:奇怪的NullPointerException_Java_Nullpointerexception_Linked List - Fatal编程技术网

Java-LinkedList:奇怪的NullPointerException

Java-LinkedList:奇怪的NullPointerException,java,nullpointerexception,linked-list,Java,Nullpointerexception,Linked List,我对NullPointerException有一个小问题,我不能真正理解 我的代码全天候运行,运行得很好,但我有一个例外,在应用程序启动后的1天到1周内随机弹出 以下是stacktrace: java.lang.NullPointerException at java.util.LinkedList.get(LinkedList.java:477) at com.ch4process.acquisition.ScenarioWorker.eventHandling(ScenarioWorker.

我对NullPointerException有一个小问题,我不能真正理解

我的代码全天候运行,运行得很好,但我有一个例外,在应用程序启动后的1天到1周内随机弹出

以下是stacktrace:

java.lang.NullPointerException
at java.util.LinkedList.get(LinkedList.java:477)
at com.ch4process.acquisition.ScenarioWorker.eventHandling(ScenarioWorker.java:97)
at com.ch4process.acquisition.ScenarioWorker.call(ScenarioWorker.java:79)
at com.ch4process.acquisition.ScenarioWorker.call(ScenarioWorker.java:1)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
正如您所看到的,这个异常是在线程中引发的

下面是代码(简化了一点):

公共类ScenarioWorker实现可调用
{
List eventList=new LinkedList();
布尔忙=假;
@凌驾
公共整数调用()引发异常
{
尝试
{
while(true)
{
事件处理();
睡眠(1000);
}
}
捕获(例外情况除外)
{
//将异常重定向到自定义类
}
}
私有void事件处理()
{
如果(!忙)
{
while(eventList.size()>0)
{       
SignalValueEvent=eventList.get(0);//此处根据stacktrace的NullPointerException
if(event.isTriggered())
{
忙=真;
doScenario(事件);
}
deleteEvent();
}
}
}
私有void deleteEvent()
{
尝试
{
事件列表。删除(0);
}
捕获(例外情况除外)
{
//将异常重定向到自定义类
}
最后
{
忙=假;
}
}
@凌驾
public void SignalValueChanged(SignalValueEvent事件)
{
if(event.isValid())
{
添加(事件);
}
}
}

[编辑:stacktrace中的第97行表示SignalValueEvent=eventList.get(0);]

此类实现了一个接口,该接口允许另一个类通过调用SignalValueChanged方法来通知它

因此,基本上我的LinkedList是在类初始化时创建的,每当需要将事件放入列表时,由外部类填充,调用方法在列表上循环以查看其中是否有任何内容。如果有,将对其进行处理并删除事件

我已经测试过了,我应该有一个NPException的唯一原因是如果我的列表等于null。。。但在我的代码中我没有这样做

正如我所说的,这段代码是全天候工作的,在我启动应用程序将近一周半后,我就出现了这个bug。是不是有什么明显的东西我遗漏了


非常感谢您阅读本文,如果您能帮助我,我将非常高兴:)

正如上面所说的,我猜这是一个并发问题

最有可能的情况是,在调用
eventList.get(0)
时,尽管“刚刚”测试了列表是否为空,但通过另一个并发线程,列表变为null或列表变为空

编辑:正如在对问题的评论中所讨论的,NullPointerException是从LinkedList的内部工作中抛出的,这意味着它肯定是一个并发问题


让你的对象线程安全,你就会解决这个问题。

我认为这也与线程同步有关。解决方案:使用
synchronized
方法将
eventList
封装到对象中。仅通过调用这些同步方法从所有线程访问
eventList

只需阅读:

请注意,此实现未同步。如果多个线程同时访问链接列表,并且至少有一个线程在结构上修改了该列表,则必须在外部对其进行同步。(结构修改是添加或删除一个或多个元素的任何操作;仅设置元素的值不是结构修改。)这通常通过在自然封装列表的某个对象上进行同步来实现。如果不存在此类对象,则应使用Collections.synchronizedList方法“包装”列表。最好在创建时执行此操作,以防止意外不同步地访问列表:

List List=Collections.synchronizedList(新的LinkedList(…)


NPE不是空的,因为列表是空的——如果是空的,则异常的根将位于
ScenarioWorker.java
第97行。相反,代码正在将其放入
LinkedList
的内部,这表明
LinkedList
实现内部的某些东西正在出错,这是并发问题的一个巨大危险信号。至于原因,可能是一个调用
SignalValueChanged
的线程中的一个争用,以及另一个调用
eventHandling
的线程中的另一个争用


您可以通过同步对
事件列表的所有访问来解决此问题。最简单的方法可能只是将方法
SignalValueChanged
eventHandling
标记为
synchronized

1)第97行是哪一行<代码>ScenarioWorker.java:97
2)代码是现在每次运行都失败,还是间歇性失败?3) 如果是间歇性的,则表明存在并发问题。您确定您的代码是线程安全的吗?@HovercraftFullOfEels:97行是SignalValueEvent=eventList.get(0);我将编辑我的帖子来反映这一点。这个问题是间歇性的,我认为LinkedList是线程安全的?“实践中的Java并发”-抓住这本书,深入研究它。如果你不这样做,你将永远生活在痛苦的世界中。请注意,NPE不是因为你的列表是空的——如果是空的,那么异常的根将位于ScenarioWorker.java第97行。相反,代码将其放入LinkedList的内部,这表明LinkedList实现内部的某些东西正在出错——这是并发问题的一个巨大危险信号。至于原因,可能是一个线程调用SignalValueChanged,而另一个线程同时调用eventHandling。@KevinEsche:这绝对不是你所提问题的重复,因为NPE与变量为null无关,而是与
public class ScenarioWorker implement Callable<Integer>
{
List<SignalValueEvent> eventList = new LinkedList<>();

boolean busy = false;

@Override
public Integer call() throws Exception
{
    try
    {
        while (true)
        {
            eventHandling();
            Thread.sleep(1000);
        }
    }
    catch (Exception ex)
    {
        // Redirects the exception to a custom class
    }
}

private void eventHandling()
{
    if (! busy)
    {
        while (eventList.size() > 0)
        {       
            SignalValueEvent event = eventList.get(0); // NullPointerException here according to stacktrace

            if(event.isTriggered()))
            {
                busy = true;
                doScenario(event);
            }
            deleteEvent();
        }
    }
}


private void deleteEvent()
{
    try
    {
        eventList.remove(0);
    }
    catch (Exception ex)
    {
        // Redirects the exception to custom class
    }
    finally
    {
        busy = false;
    }
}


@Override
public void SignalValueChanged(SignalValueEvent event)
{
    if (event.isValid())
    {
        eventList.add(event);
    }
}