2015-10-23 9 views
9

Ich versuche Maximum Waiting Time in meinem PQueue zu setzen. Diese Maximum Waiting Time wird automatisch überprüfen, PQueue, wenn es links warten mehr als Maximum Waiting Time, um es zu entfernen. Ich habe diese Änderungen an meinem Code es funktioniert, aber es stoppt genau nach dem Entfernen der Links. Ich möchte alle Elemente aus meinem PQueue je nach Wartezeit entfernen. Kannst du mir sagen, was ich hier vermisse?Wie Elemente aus PriorityQueue nach einer Elementeigenschaft entfernen?

Das ist meine Klasse:

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

Haben nicht sah durch den gesamten Code, aber die Synchronisierung auf "InterLinkCount" oder "IntraLinkCount" funktioniert nicht. Sie ändern ständig, auf welches Objekt sich diese Variablen beziehen, sodass verschiedene Threads nicht die gleichen Sperren erhalten. – user2357112

+0

@ user2357112 das ist nicht mein ganzes Projekt, da es ein großes Programm ist. Dies ist ein Teil davon. Ich kann bei Bedarf andere Prozeduren bezüglich des Codes bereitstellen – medo0070

+0

Ein genereller Kommentar: Verwenden Sie nicht 'new Integer (n)', sondern verwenden Sie 'Integer.valueOf (n)'. Es ist viel effizienter. – Tomas

Antwort

3

Ihre Frage ein bisschen undurchsichtig ist, aber wenn ich es richtig verstehe, wollen Sie Ihre PriorityQueue, um zu prüfen, ob es Elemente, die als eine bestimmte Zeit länger gewartet.

Ihre Verwendung von synchronized auf der IntraLinkCount und InterLinkCount ist, wie bereits erwähnt, ein bisschen seltsam. Es gibt eine ziemlich unbekannte Alternative ist, das Atom integer Klasse AtomicInteger (im Paket java.util.concurrent.atomic:..

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

Dies funktioniert, wie Sie wollen

Das zweite Problem ist, dass Sie die poll() Methode Dies wird entfernen das oberste Element aus der Warteschlange. Vielleicht sind Sie nur peek() statt, und dann remove() wenn die zurückgegebenen Verbindungsobjekt erfüllt verwenden verwenden möchten link.waitingInQueue() > MaxWaitTime?

By the way, y Unsere Warteschlange wird Artikel gemäß ihrer "natürlichen Reihenfolge" zurückgeben. Dies bedeutet, dass die Methode compareTo verwendet wird und der "kleinste" zuerst aus der Warteschlange zurückgegeben wird. Ich denke, dass Sie eine benutzerdefinierte compareTo implementieren möchten, die die längste wartende Verknüpfung zuerst setzt?

Sie könnten auch stattdessen create your PriorityQueue with a custom Comparator Objekt.

Etwas wie folgt aus:

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

Wenn Sie das Glück haben, auf Java 8 zu sein, wie dies einige Magie könnte stattdessen nützlich sein:

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

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

Es scheint mir, dass es keinen Grund für "MaxWaitTime" gibt, ein "Integer" anstelle von "int" zu sein. Und die statischen Variablen 'final' zu machen würde nicht weh tun ... – Holger

+0

Da der Code von der Frage kopiert wird, solltest du stattdessen den Kommentar dort setzen? – Tomas

+0

Da Sie bereits zwei der 'Integer's in' AtomicInteger' umgewandelt haben, können Sie die letzte in 'int' konvertieren, um alle' Integer's loszuwerden ... Allerdings gilt die Empfehlung, die Variablen 'final' zu machen sie alle, vor allem die AtomicInteger. – Holger

Verwandte Themen