【问题标题】:How to Remove Elements from PriorityQueue according to a Element Property?如何根据元素属性从 PriorityQueue 中删除元素?
【发布时间】:2016-01-22 22:04:12
【问题描述】:

我尝试在我的PQueue 中设置Maximum Waiting Time。这个Maximum Waiting Time 将自动检查我的PQueue,如果有任何links 等待超过Maximum Waiting Time 来删除它。我对正在运行的代码进行了此更改,但在删除链接后它完全停止了。我想根据等待时间条件从我的PQueue 中删除所有元素。你能告诉我我在这里缺少什么吗?

这是我的课:

public class MyClass {

    public static PriorityQueue <LinkNodeLight> PQueue = new PriorityQueue <> (); 


    private static Set<String> DuplicationLinksHub = new LinkedHashSet <> ();         

    private static Integer IntraLinkCount = new Integer (0);                 
    private static Integer InterLinkCount = new Integer (0);                 
    private static Integer DuplicationLinksCount = new Integer (0);     
    private static Integer MaxWaitTime = new Integer (60000); // 1 M= 60000 MS


    @SuppressWarnings("null")
    LinkNode deque(){

        LinkNode link = null;
        synchronized (PQueue) {

            link = (LinkNode) PQueue.poll();
            if (link != null) {
                link.setDequeTime(new DateTime());
                if (link.isInterLinks())
                    synchronized (InterLinkCount) {
                        InterLinkCount--;
                        }
                else
                    synchronized (IntraLinkCount) {
                        IntraLinkCount--;
                        }
            }

            synchronized (PQueue) {
                if (link.waitingInQueue()>MaxWaitTime) {

                    link = (LinkNode) PQueue.remove();
                                    System.out.println("*********************************");
                                    System.out.println("This Link is Deopped: " + link);
                                    System.out.println("%%% MaX Waiting Time:" + (MaxWaitTime/60000)+"Min");

                                    System.out.println("*********************************");
                  }
            }
            return link;


        }

【问题讨论】:

  • 尚未查看您的所有代码,但在 InterLinkCountIntraLinkCount 上同步不起作用。您不断更改这些变量引用的对象,因此不同的线程不会获取相同的锁。
  • @user2357112 这不是我的整个项目,因为它是一个大程序。这是其中的一部分。如果需要,我可以提供有关代码的其他程序
  • 一般性评论:不要使用new Integer(n),而是使用Integer.valueOf(n)。效率更高。
  • 永远不要在可变变量上同步! synchronized(IntraLinkCount){IntraLinkCount--;} 不是线程安全的!
  • @Holger 那你更喜欢用什么来代替 synchronized(IntraLinkCount){IntraLinkCount--;} 我应该怎么用呢?

标签: java search priority-queue


【解决方案1】:

您的问题有点不透明,但如果我理解正确,您想检查您的PriorityQueue 以查看是否有等待时间超过特定时间的项目。

正如已经提到的,您在IntraLinkCountInterLinkCount 上使用synchronized 有点奇怪。有一个相当未知的替代方案,原子整数类AtomicInteger(在包java.util.concurrent.atomic中:

private static AtomicInteger IntraLinkCount = Integer.valueOf(0);

这将按您的意愿工作。

第二个问题是你使用了poll() 方法。这将从队列中删除顶部项目。也许您想改用peek(),然后仅在返回的链接对象满足link.waitingInQueue() &gt; MaxWaitTime 时才使用remove()

顺便说一下,您的队列将根据“自然顺序”返回项目。这意味着使用compareTo 方法,“最小的”将首先从队列中返回。我想您可能想要实现一个自定义的compareTo,将最长等待时间链接放在首位?

您也可以改为create your PriorityQueue with a custom Comparator 对象。

类似这样的:

public class MyClass {
    public static PriorityQueue<LinkNodeLight> PQueue = new PriorityQueue<>();

    private static AtomicInteger IntraLinkCount = new AtomicInteger(0);
    private static AtomicInteger InterLinkCount = new AtomicInteger(0);

    private static Integer MaxWaitTime = Integer.valueOf(60_000); // 1 M= 60000 MS

    LinkNode deque() {
        LinkNode link = null;

        synchronized (PQueue) {
            link = PQueue.peek();

            if (link != null) {
                link.setDequeTime(LocalDateTime.now());

                if (link.isInterLinks())
                    InterLinkCount.decrementAndGet();
                else
                    IntraLinkCount.decrementAndGet();

                if (link.waitingInQueue() > MaxWaitTime) {
                    link = PQueue.remove();

                    System.out.println("*********************************");
                    System.out.println("This Link is Deopped: " + link);
                    System.out.println("%%% MaX Waiting Time:" + MaxWaitTime / 60000 + "Min");
                    System.out.println("*********************************");

                    return link;
                } else
                    return null;
            }
        }

        return link; // Not sure what you want to return here
    }
}

如果您有幸使用 Java 8,那么像这样的魔法可能会很有用:

synchronized (PQueue) {
    link = PQueue.stream().filter(node -> node.waitingInQueue() > MaxWaitTime).findFirst().orElse(null);

    if (link != null)
        PQueue.remove(link);
}

【讨论】:

  • 在我看来,MaxWaitTime 没有理由成为Integer 而不是int。并且使静态变量final 不会受到伤害……
  • 由于该代码是从问题中复制的,也许您应该将评论放在那里?
  • 由于您已经将两个Integers 转换为AtomicInteger,您可以将最后一个转换为int 以摆脱所有Integers... 但是,建议使变量final 适用于所有变量,尤其是 AtomicIntegers。
  • 顺便说一句。如果您使用 Java 8,则可以更简单:PQueue.removeIf(node -&gt; node.waitingInQueue() &gt; MaxWaitTime);...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-09-18
  • 2013-09-22
  • 1970-01-01
  • 2018-09-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多