2013-05-22 39 views
3

哪一個應該選擇這些程序中的另一個,爲什麼?通常問題是爲什麼我應該選擇使用PriorityQueue上的PriorityBlockingQueue。PriorityQueue和PriorityBlockingQueue

的PriorityBlockingQueue

import java.util.concurrent.PriorityBlockingQueue; 

public class PriorityBlockingQueueExample { 

    static PriorityBlockingQueue<String> priorityQueue = new PriorityBlockingQueue<String>(); 
    public static void main(String[] args) { 

     new Thread(){ 
      public void run(){ 
       try { 
       System.out.println(priorityQueue.take() +" is removed from priorityQueue object"); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       }  
      } 
     }.start(); 
     new Thread(){ 
      public void run(){ 
       priorityQueue.add("string variable"); 
       System.out.println("Added an element to the queue"); 
      } 
     }.start(); 
    } 
} 

哪一個我應該選擇在彼此之間這些程序,爲什麼?通常問題是爲什麼我應該選擇使用PriorityQueue上的PriorityBlockingQueue。 的PriorityQueue

import java.util.PriorityQueue; 

public class PriorityQueueTest { 

    static PriorityQueue<String> priorityQueue = new PriorityQueue<String>(); 
    private static Object lock = new Object(); 
    public static void main(String[] args) { 

     new Thread(){ 
      public void run(){ 
       synchronized(lock){  
        try { 
         while(priorityQueue.isEmpty()){lock.wait();} 
          System.out.println(priorityQueue.remove() +" is removed from priorityQueue object"); 
          lock.notify(); 
        } catch (InterruptedException e) { 
          // TODO Auto-generated catch block 
          e.printStackTrace(); 
        } 
       } 
      } 
     }.start(); 
     new Thread(){ 
      public void run(){ 
       synchronized(lock){ 
        priorityQueue.add("string variable"); 
        System.out.println("Added an element to the queue"); 
        lock.notify(); 
       } 
      } 
     }.start(); 
    } 
} 

回答

5

的PriorityBlockingQueue加入與JDK 5見concurrent包:http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/package-summary.html

它基本上引擎蓋做你PriorityQueue中寫道添加常用必要的同步/等待的額外的代碼下/左右通知你的隊列中。因此,名稱的「阻塞」部分被添加以暗示線程將阻塞等待,直到隊列上有可用項目。

如果您的應用程序可以在JDK 5或更新的版本上運行,那麼我會使用PriorityBlockingQueue。

13

正常Queue將訪問時,如果它是空的,而一個BlockingQueue如果隊列爲空,直到值可用返回null

優先部分使用的是簡單的隊列是指物品從隊列中按照特定的順序讀取(無論是天然的,如果他們實施Comparable或根據Comparator)。

通常,您應該可以依賴於抽象類型PriorityQueueBlockingQueue。如果你的代碼需要這些概念的知識,可能需要重新思考。

有很多原因可能導致您需要PriorityQueue歸結爲消息排序。例如,在作業隊列中,您可能希望能夠優先處理這些作業。這就是說,處理這些工作的代碼通常應該與訂單無關。

通過BlockingQueue,您通常處於工作線程領域,領取排隊的工作,當無需執行任何工作時,可阻止這些線程直到工作可用。像PriorityQueue的示例一樣,調用代碼可能與此無關,但您可能希望使用某種等待超時,但並非總是如此。

1

我知道這是一個老話題,但我看到你沒有考慮優先級隊列的併發實現。

雖然Java的集合框架沒有一個,它確實有足夠的構建塊來創建一個:

public class ConcurrentSkipListPriorityQueue<T> implements Queue<T> { 

    private ConcurrentSkipListMap<T, Boolean> values; 

    public ConcurrentSkipListPriorityQueue(Comparator<? super T> comparator) { 
     values = new ConcurrentSkipListMap<>(comparator); 
    } 

    public ConcurrentSkipListPriorityQueue() { 
     values = new ConcurrentSkipListMap<>(); 
    } 

    @Override 
    public boolean add(T e) { 
     values.put(e, Boolean.TRUE); 
     return true; 
    } 

    @Override 
    public boolean offer(T e) { 
     return add(e); 
    } 

    @Override 
    public T remove() { 
     while (true) { 
      final T v = values.firstKey(); 
      if (values.remove(v)) { 
       return v; 
      } 
     } 
    } 

    @Override 
    public T poll() { 

     try { 
      while (true) { 
       if (values.isEmpty()) { 
        return null; 
       } 
       final T v = values.firstKey(); 
       if (values.remove(v)) { 
        return v; 
       } 
      } 
     } catch (NoSuchElementException ex) { 
      return null; // poll should not throw an exception.. 
     } 
    } 

    @Override 
    public T element() { 
     return values.firstKey(); 
    } 

    @Override 
    public T peek() { 
     if (values.isEmpty()) { 
      return null; 
     } 

     try { 
      return element(); 
     } catch (NoSuchElementException ex) { 
      return null; 
     } 
    } 

    @Override 
    public int size() { 
     return values.size(); 
    } 

    @Override 
    public boolean isEmpty() { 
     return values.isEmpty(); 
    } 

    @Override 
    public boolean contains(Object o) { 
     return values.containsKey(o); 
    } 

    @Override 
    public Iterator<T> iterator() { 
     return values.keySet().iterator(); 
    } 

    @Override 
    public Object[] toArray() { 
     return values.keySet().toArray(); 
    } 

    @Override 
    public <T> T[] toArray(T[] a) { 
     return values.keySet().toArray(a); 
    } 

    @Override 
    public boolean remove(Object o) { 
     return values.remove(o); 
    } 

    @Override 
    public boolean containsAll(Collection<?> c) { 
     return values.keySet().containsAll(c); 
    } 

    @Override 
    public boolean addAll(Collection<? extends T> c) { 

     boolean changed = false; 

     for (T i : c) { 
      changed |= add(i); 
     } 

     return changed; 
    } 

    @Override 
    public boolean removeAll(Collection<?> c) { 
     return values.keySet().removeAll(c); 
    } 

    @Override 
    public boolean retainAll(Collection<?> c) { 
     return values.keySet().retainAll(c); 
    } 

    @Override 
    public void clear() { 
     values.clear(); 
    } 

} 

此隊列受委託其所有操作的ConcurrentSkipListMap類基於跳躍列表上。它允許來自多個線程的非阻塞併發訪問。