2015-10-23 2 views
9

Я пытаюсь установить Maximum Waiting Time внутри моего PQueue. Это Maximum Waiting Time будет проверять мой PQueue автоматически, если есть links, ждущие более Maximum Waiting Time, чтобы удалить его. Я сделал это, изменив мой код, он работает, но он останавливается именно после удаления ссылок. Я хочу удалить все элементы из моего PQueue в соответствии с условием ожидания. Можете ли вы рассказать мне, что мне здесь не хватает?Как удалить элементы из PriorityQueue в соответствии с свойством Element?

Это мой класс:

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; 


     } 
+0

Не просмотрел весь код, но синхронизация на 'InterLinkCount' или' IntraLinkCount' не работает. Вы продолжаете изменять объект, к которому относятся эти переменные, поэтому разные потоки не получают одинаковые блокировки. – user2357112

+0

@ user2357112 это не весь мой проект, так как это большая программа. Это часть его. Я могу предоставить другие процедуры, касающиеся кода, если это необходимо – medo0070

+0

Общий комментарий: не используйте 'new Integer (n)', вместо этого используйте 'Integer.valueOf (n)'. Это намного эффективнее. – Tomas

ответ

3

Ваш вопрос немного непрозрачным, но если я правильно понимаю вы хотите проверить PriorityQueue, чтобы увидеть, если есть элементы, которые ждали дольше определенного времени.

Ваше использование synchronized на IntraLinkCount и InterLinkCount, как уже упоминалось, немного странно. Существует достаточно неизвестной альтернативы, атомное число класса AtomicInteger (в пакете java.util.concurrent.atomic:..

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

Это будет работать, как вы хотите

Вторая проблема заключается в том, что вы используете метод poll() Это будет удалить верхний элемент из очереди. Может быть, вы хотите использовать вместо peek(), а затем использовать только remove() если возвращенную ссылку объект удовлетворяет link.waitingInQueue() > MaxWaitTime?

Кстати, у наша очередь будет возвращать элементы в соответствии с их «естественным порядком». Это означает, что используется метод 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); 
} 
+0

Мне кажется, что 'MaxWaitTime' не является причиной' Integer' вместо 'int'. И сделать статические переменные 'final' не повредит ... – Holger

+0

Поскольку код скопирован из вопроса, возможно, вы должны поставить комментарий там вместо этого? – Tomas

+0

Поскольку вы уже преобразовали два из 'Integer' в 'AtomicInteger', вы можете преобразовать последний в' int', чтобы избавиться от всех 'Integer' ... Однако рекомендация о том, чтобы переменные 'final' применимы к все они, особенно * «AtomicInteger's». – Holger

Смежные вопросы