Java - LinkedList:奇怪的NullPointerException

时间:2017-01-02 13:47:18

标签: 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.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)

正如您所看到的,这个异常在一个帖子中出现了。

这是代码(简化了一下):

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);
    }
}

}

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

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

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

我已经测试了这个并且我应该有一个NPException的唯一原因是我的列表是否等于null ...但我不会在我的代码中的任何地方这样做...

正如我所说,这段代码全天候工作,我在启动应用程序后差不多一周半就遇到了这个错误。这是我想念的东西吗?

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

4 个答案:

答案 0 :(得分:4)

NPE不是因为你的列表是空的 - 如果是,你的例外的根将在ScenarioWorker.java第97行。相反,代码正在进入LinkedList的内部,这表明LinkedList实现内部的东西被搞砸了 - 并发问题的一个巨大的红旗。至于为什么,可能是一个线程中的竞赛同时调用SignalValueChanged和另一个调用eventHandling

您可以通过同步eventList的所有访问权来解决此问题。最简单的方法可能就是将方法SignalValueChangedeventHandling标记为synchronized

答案 1 :(得分:3)

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

答案 2 :(得分:1)

正如上面提到的Hovercraft Full Of Eels所说,我猜这是一个并发问题。

最有可能的是,当您拨打eventList.get(0)时,尽管有&#34;只是&#34;测试列表不为空,列表变为空或列表变为空,通过另一个并发线程。

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

让您的对象具有线程安全性,您将解决问题。

答案 3 :(得分:1)

请阅读LinkedLists JavaDoc

  

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

     

List list = Collections.synchronizedList(new LinkedList(...));