2015-10-23 38 views
9

Próbuję ustawić Maximum Waiting Time w moim PQueue. Ta Maximum Waiting Time automatycznie sprawdzi moją PQueue, jeśli są jakieś links, które czekają dłużej niż Maximum Waiting Time, aby ją usunąć. Wprowadziłem zmiany do mojego kodu, który działa, ale zatrzymuje się dokładnie po usunięciu linków. Chcę usunąć wszystkie elementy z mojego PQueue zgodnie z warunkami czasu oczekiwania. Czy możesz mi powiedzieć, czego tu brakuje?Jak usunąć elementy z PriorityQueue zgodnie z właściwością elementu?

To moja klasa:

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

nie wyglądał przez cały kodzie, ale synchronizacja na 'InterLinkCount' lub' IntraLinkCount' nie działa. Ciągle się zmieniasz, do którego obiektu odnoszą się te zmienne, więc różne wątki nie nabywają tych samych zamków. – user2357112

+0

@ user2357112 to nie jest mój cały projekt, ponieważ jest to duży program. To jest część tego. W razie potrzeby mogę podać inne procedury dotyczące kodu. – medo0070

+0

Komentarz ogólny: nie używaj "nowej liczby całkowitej (n)", zamiast tego użyj wyrażenia "Integer.valueOf (n)". Jest o wiele bardziej wydajny. – Tomas

Odpowiedz

3

Twoje pytanie jest nieco nieprzejrzysty, ale jeśli rozumiem go poprawnie chcesz sprawdzić PriorityQueue aby sprawdzić, czy istnieją elementy, które czekali dłużej niż określony czas.

Używanie synchronized na IntraLinkCount i InterLinkCount jest, jak już wspomniano, nieco dziwne. Jest to dość nieznany alternatywa atomowy klasy całkowitą AtomicInteger (w pakiecie java.util.concurrent.atomic:..

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

to będzie działać jak chcesz

Drugim problemem jest to, że użycie metody poll() Będzie to usuń górny element z kolejki. Może chcesz użyć peek() zamiast, a następnie użyć tylko remove() Jeśli zwrócona wynikowych spełnia link.waitingInQueue() > MaxWaitTime?

Nawiasem mówiąc, y nasza kolejka zwróci przedmioty zgodnie z ich "naturalną kolejnością". Oznacza to, że używana jest metoda compareTo, a "najmniejsza" zostanie zwrócona z kolejki jako pierwsza. Myślę, że może chciałbyś zaimplementować niestandardowy compareTo, który zamiast tego wstawia najdłuższy oczekujący link ?

Można również użyć obiektu create your PriorityQueue with a custom Comparator.

coś takiego:

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 
    } 
} 

Jeśli masz szczęście wystarczy, aby być na Java 8, jakaś magia jak to może być użyteczne zamiast:

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

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

Wydaje mi się, że nie ma powodu dla 'MaxWaitTime' być' Integer' zamiast 'int'. A sprawienie, by zmienne statyczne "ostateczne" nie zaszkodziły ... – Holger

+0

Skoro ten kod jest skopiowany z pytania, może powinieneś umieścić tam komentarz? – Tomas

+0

Ponieważ już konwertowałeś dwa z 'Integer's na' AtomicInteger', możesz przekonwertować ostatni na 'int', aby pozbyć się wszystkich' Integer's ... Jednak zalecenie, aby zmienne 'final' odnosiło się do wszystkie, * szczególnie * 'AtomicInteger's. – Holger