首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >Java - LinkedList :怪异的NullPointerException

Java - LinkedList :怪异的NullPointerException
EN

Stack Overflow用户
提问于 2017-01-02 13:47:18
回答 3查看 1.8K关注 0票数 3

我对NullPointerException有一个小问题,我无法真正理解它。

我的代码运行24/7,运行良好,但我有一个异常,在应用程序启动后1天到1周之间随机弹出。

下面是堆栈跟踪:

代码语言:javascript
运行
复制
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)

如您所见,此异常在线程中上升。

下面是代码(稍微简化一下):

代码语言:javascript
运行
复制
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);
    }
}

}

编辑:堆栈跟踪中的第97行表示SignalValueEvent事件= eventList.get(0);

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

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

我对此进行了测试,我应该拥有一个NPException的唯一原因是如果我的列表等于null.但在我的代码里我不会这么做..。

正如我说过的,这段代码是24/7工作的,在启动应用程序后的将近一周半时间里,我就有了这个错误。我错过了什么明显的东西吗?

谢谢你阅读这篇文章,如果你能帮我的话,我会很高兴的:)

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-01-02 15:11:18

NPE并不是因为您的列表为null --如果是的话,异常的根将位于ScenarioWorker.java第97行。相反,代码正在将其放入LinkedList的内部,这表明LinkedList实现的内部功能被搞砸了--这是并发问题的一个巨大危险标志。至于为什么,可能是一个线程中的一个线程调用SignalValueChanged,另一个线程同时调用eventHandling

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

票数 4
EN

Stack Overflow用户

发布于 2017-01-02 13:56:28

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

票数 3
EN

Stack Overflow用户

发布于 2017-01-02 14:57:02

只需阅读s JavaDoc

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41428055

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档