Java 具有PriorityBlockingQueue的NullPointerException

Java 具有PriorityBlockingQueue的NullPointerException,java,multithreading,priority-queue,Java,Multithreading,Priority Queue,在自定义线程拉取中使用PriorityBlockingQueue时遇到了一个问题,其中poll方法会导致NullPointerException。使用此设置时 int POOL_SIZE = 5; int OVERHEAD_POOL_SIZE = 10; long LIFE_TIME = 5000; TimeUnit LIFE_TIME_UNIT = TimeUnit.MILLISECONDS; 与 基本上,我想在队列中按优先级排序Runnables: class MyRunnableFutu

在自定义线程拉取中使用
PriorityBlockingQueue
时遇到了一个问题,其中poll方法会导致
NullPointerException
。使用此设置时

int POOL_SIZE = 5;
int OVERHEAD_POOL_SIZE = 10;
long LIFE_TIME = 5000;
TimeUnit LIFE_TIME_UNIT = TimeUnit.MILLISECONDS;

基本上,我想在队列中按优先级排序
Runnable
s:

class MyRunnableFuture implements 
        RunnableFuture<Boolean>, Comparable<MyRunnableFuture>
类MyRunnableFuture实现
可比运行未来
连线的事情是:异常并不总是被抛出,但是如果我在
PriorityQueue.siftDownComparable
中设置了一个断点,则异常发生的几率更高


有什么想法吗?我找到了其他人,但没有人真正知道解决办法。在
线程池中使用时,是否必须手动同步队列?我正在使用队列,因为我不想同步它。我理解这些描述,好像队列已经在内部同步了?谢谢你的回答

阅读下面的评论后更新:所有问题都是由于使用
submit
而不是
execute
造成的,在前者中,所有线程都封装在一个
RunnableFuture
内部,当然不实现
可比较的
接口。这就是比较失败的原因。我被
NullPointerException
分散了注意力,这是由于新的工作线程试图提取以前无法插入的作业时引起的。(线索是:
PriorityBlockingQueue
没有插入新作业,因为抛出了
ClassCastException
。与此同时,
ThreadPoolExecutor
认为有一个新作业可用,并提醒下一个工作者。工作者提取一个不存在的作业并抛出
nullpointerxception
ClassCastException
被吞没并深入到我的应用程序中,我没有足够仔细地跟踪它,因为我试图找到
NullPointerException
的原因

为完整起见,
ThreadPoolExecutor
的submit方法实际上执行以下操作:

public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}
公共未来提交(可运行任务){
如果(task==null)抛出新的NullPointerException();
RunnableFuture ftask=newTaskFor(任务,空);
执行(ftask);
返回ftask;
}
感谢你们的帮助(在评论中!)


PS:Mean bug.

PriorityBlockingQueue
PriorityQueue
封装在锁中。您当然不应该对其进行自己的锁定。我认为这方面有缺陷记录,请阅读对缺陷的评论,但是:"我们怀疑这是库中的一个bug。这更可能是用户程序中的一个bug。为了能够重现这种问题,我们确实需要一个只使用核心JDK API的小型可重现测试用例。请注意,PriorityQueue不是线程安全的,并且可靠性问题只在使用多线程时发生s、 这再次表明用户程序有故障。"我是在Jersey的上下文中使用它的。如果我跳过Jersey接口,问题就永远不会发生。这可能与延迟较少有关。在这过程中,您是否有可能修改可比较的
Runnable
一、 但是,您的池分配的线程永远不会超过5个。不幸的是,
ThreadPoolExecutor
在分配超过核心线程之前填充队列。由于您的队列没有边界,因此它永远不会失败
offer()
call。每次使用
submit
而不是
execute
时,您的
threadpoolexecuter
都会将
RunnableFuture
排队,而不是
MyRunnable
,除非您重写执行器的工厂方法。但我希望
ClassCastException
中的值为s,而不是
null
这种情况。好的,这很可能就是问题所在:
ClassCastException
(s)发生,例如在插入时,但它们在某些地方被捕获和忽略。但此时,队列已经更新了其
大小
字段。因此,它将在稍后的时间失败,NPE尝试访问从未存储的项目。FML。我甚至不知道我使用了
提交
而不是
执行
。这是由c完成的我们解决了我的问题。我发现一些后台线程导致了
ClassCastException
,而另一些线程产生了
nullpointerxception
。使用
execute
而不是
submit
使这两个线程都消失了。
class MyRunnableFuture implements 
        RunnableFuture<Boolean>, Comparable<MyRunnableFuture>
public Future<?> submit(Runnable task) {
    if (task == null) throw new NullPointerException();
    RunnableFuture<Void> ftask = newTaskFor(task, null);
    execute(ftask);
    return ftask;
}