首页 > 解决方案 > Java PriorityQueue NPE 即使添加的元素不为空?

问题描述

我正在尝试在以下代码中使用 Java PriorityQueue 类:

private static PriorityQueue<String> commandQueue = new PriorityQueue<String>();
private static boolean looping = false;

public static void startCommandHandling() {
    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
            if (!looping) {
                while (!commandQueue.isEmpty()) {
                    looping = true;
                    String command = commandQueue.poll();
                    if (Main.communicationPort.isOpen()) {
                        String string = "!" + command + "\r\n";
                        byte[] data = string.getBytes();
                        int dataLength = data.length;
                        Main.communicationPort.writeBytes(data, dataLength);
                    }
                }
                looping = false;
            }
        }
    }, 1, 1);
}

public static void sendCommand(String command) {
    commandQueue.add(command);
}

public static void sendCommands(List<String> commands) {
    commandQueue.addAll(commands);
}

它用于对串行端口命令进行排队,以便一个接一个地发送它们。我确定我没有将任何空字符串提供给 sendCommand() 或 sendCommands() 方法——在调用这些方法的地方有一个空检查。它有时不会在任务被调度并将第一个命令添加到队列后立即抛出此异常,但很多时候添加新命令会导致 NPE 和 Java 应用程序崩溃:

Exception in thread "Timer-0" Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:61)
Caused by: java.lang.NullPointerException
    at java.lang.String.compareTo(String.java:1155)
    at java.lang.String.compareTo(String.java:111)
    at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:656)
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:647)
    at java.util.PriorityQueue.offer(PriorityQueue.java:344)
    at java.util.PriorityQueue.add(PriorityQueue.java:321)
    at java.util.AbstractQueue.addAll(AbstractQueue.java:187)
    at com.rpiled.SerialCommands.sendCommands(SerialCommands.java:114)
    at com.rpiled.UserSettings.apply(UserSettings.java:31)
    at com.rpiled.Main.main(Main.java:32)
    ... 5 more
java.lang.NullPointerException
    at java.util.PriorityQueue.siftDownComparable(PriorityQueue.java:701)
    at java.util.PriorityQueue.siftDown(PriorityQueue.java:689)
    at java.util.PriorityQueue.poll(PriorityQueue.java:595)
    at com.rpiled.SerialCommands$1.run(SerialCommands.java:46)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)
root@raspberrypi:~#

我怀疑这与命令轮询是在每 1 毫秒调用一次的任务中完成的事实有关,但我需要它经常运行,因为我需要尽可能快地发送命令,同时仍然不允许它们相互混合 - 即不能同时发送两个命令(这就是需要队列系统的原因)。我用这段代码做了很多实验,发现创建新的 PriorityQueue 对象并添加例如 500 ( ...= new PriorityQueue<String>(500);) 的初始容量值会导致不再有应用程序崩溃和 NPE 有点不同:

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:61)
Caused by: java.lang.NullPointerException
    at java.lang.String.compareTo(String.java:1155)
    at java.lang.String.compareTo(String.java:111)
    at java.util.PriorityQueue.siftUpComparable(PriorityQueue.java:656)
    at java.util.PriorityQueue.siftUp(PriorityQueue.java:647)
    at java.util.PriorityQueue.offer(PriorityQueue.java:344)
    at java.util.PriorityQueue.add(PriorityQueue.java:321)
    at java.util.AbstractQueue.addAll(AbstractQueue.java:187)
    at com.rpiled.SerialCommands.sendCommands(SerialCommands.java:114)
    at com.rpiled.UserSettings.apply(UserSettings.java:31)
    at com.rpiled.Main.main(Main.java:32)
    ... 5 more

我该如何解决这个问题?是什么导致了 NPE?

标签: java

解决方案


推荐阅读