2009-05-21 60 views
5

這個問題與我前面的問題一個有關..阻塞隊列 - 需要更多信息

Previous Post

在有阻塞性質被提及作爲一個優勢。

我試圖開發一些簡單的代碼來演示阻塞性質,但我卡住了。我只是嘗試製作大小爲4的BlockingQueue,並嘗試添加5個元素,並以java.lang.IllegalStateException結尾。有人可以給我看一個阻止BlockingQueue性質的代碼示例嗎?


public static void main(String[] args) { 
    BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4); 

    try { 
     bq.offer("A"); 
     bq.offer("B"); 
     bq.offer("C"); 
     bq.offer("D"); 
     bq.offer("E"); 

     System.out.println("1 = " + bq.take()); 
     System.out.println("2 = " + bq.take()); 
     System.out.println("3 = " + bq.take()); 
     System.out.println("4 = " + bq.take()); 
     System.out.println("5 = " + bq.take()); 
     System.out.println("6 = " + bq.take()); 
    } catch (Exception e) { 
     // TODO: handle exception 
     e.printStackTrace(); 
    } 
} 

我用這個代碼段。在這種情況下,我試圖將5個元素放入大小爲4的隊列中。在這種情況下,應將4個元素(A,B,C,D)添加到隊列中。然後我打印時打電話給take()方法。當我致電System.out.println("1 = " + bq.take());時,是否不應該將「E」自動插入隊列中?因爲它獲得一個空閒插槽?

回答

11

是你與addoffer,或put加入?我假設你使用的是add,因爲它是唯一可以拋出IllegalStateException;但是如果您閱讀table,則會看到如果要阻止語義,則應該使用put(和take刪除)。

編輯:你的例子有幾個問題。

首先我會回答這個問題:「當我第一次給take()打電話時,E爲什麼不插入?」答案是,當您撥打take()時,您已嘗試,並且未能插入E.一旦釋放空間,就沒有插入內容。

現在如果您將offer()更改爲put(),put("E")將永遠不會返回。爲什麼?因爲它在等待其他線程從隊列中刪除元素。請記住,BlockingQueues是專爲多線程訪問。如果您有單線程應用程序,則阻塞是無用的(實際上比無用的更糟糕)。

這裏有一個改進的例子:

public static void main(String[] args) { 
    final BlockingQueue<String> bq = new LinkedBlockingQueue<String>(4); 

    Runnable producer = new Runnable() { 
     public void run() { 
      try { 
       bq.put("A"); 
       bq.put("B"); 
       bq.put("C"); 
       bq.put("D"); 
       bq.put("E"); 
      } catch (InterruptedException ex) { 
       Thread.currentThread().interrupt(); 
      } 
     } 
    }; 
    Runnable consumer = new Runnable() { 
     public void run() { 
      try { 
       System.out.println("1 = " + bq.take()); 
       System.out.println("2 = " + bq.take()); 
       System.out.println("3 = " + bq.take()); 
       System.out.println("4 = " + bq.take()); 
       System.out.println("5 = " + bq.take()); 
       System.out.println("6 = " + bq.take()); 
      } catch (InterruptedException ex) { 
       Thread.currentThread().interrupt(); 
      } 
     } 
    }; 
    new Thread(producer).start(); 
    new Thread(consumer).start(); 
} 

現在put("E")通話將真正成功,因爲它現在可以等待,直到消費者線程從隊列中刪除「A」。最後的take()仍然會無限地阻止,因爲沒有第六個元素可以刪除。

2

mmyers打我吧:P(+1)
應該是你需要的,祝你好運!

注意: put()在您的示例中將失敗,因爲put()會阻塞直到空間可用。由於空間永遠不可用,程序永遠不會繼續執行。

====舊答案======

一個BlockingQueue的是一個接口,你就必須使用implementating類之一。

「堵自然」簡單地說,你可以要求你的隊列中的東西,如果是空的,它的線程是在意志(等待),直到東西被添加到隊列,然後繼續處理。

ArrayBlockingQueue
DelayQueue
LinkedBlockingQueue
PriorityBlockingQueue
SynchronousQueue

http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html

//your main collection 
LinkedBlockingQueue<Integer> lbq = new LinkedBlockingQueue<Integer>(); 

//Add your values 
lbq.put(100); 
lbq.put(200); 

//take() will actually remove the first value from the collection, 
//or block if no value exists yet. 
//you will either have to interrupt the blocking, 
//or insert something into the queue for the program execution to continue 

int currVal = 0; 
try { 
    currVal = lbq.take(); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 

+0

謝謝..我用 「的LinkedBlockingQueue」 – 2009-05-21 13:59:47

+0

真棒,是你所需要的一切?我現在正在研究一個例子,如果你仍然希望我發佈它 – 2009-05-21 14:01:07

+0

更好地發佈它。只是一個簡短的例子:) – 2009-05-21 14:02:02

1

具體回答你的問題:提供的是一種非阻塞提供調用,因此像您發佈的一個單線程方法,調用提供(「E」),直接返回,而無需修改隊列滿假的。如果你使用阻塞放('E')呼叫,它會睡覺,直到空間可用。永遠在你的簡單例子。您需要從隊列中讀取一個單獨的線程來爲投入完成創建空間。

0

嗨更多信息此類

/** 
* Inserts the specified element into this queue if it is possible to do 
* so immediately without violating capacity restrictions, returning 
* {@code true} upon success and throwing an 
* {@code IllegalStateException} if no space is currently available. 
* When using a capacity-restricted queue, it is generally preferable to 
* use {@link #offer(Object) offer}. 
* 
* @param e the element to add 
* @return {@code true} (as specified by {@link Collection#add}) 
* @throws IllegalStateException if the element cannot be added at this 
*   time due to capacity restrictions 
* @throws ClassCastException if the class of the specified element 
*   prevents it from being added to this queue 
* @throws NullPointerException if the specified element is null 
* @throws IllegalArgumentException if some property of the specified 
*   element prevents it from being added to this queue 
*/ 
boolean add(E e); 

/** 
* Inserts the specified element into this queue if it is possible to do 
* so immediately without violating capacity restrictions, returning 
* {@code true} upon success and {@code false} if no space is currently 
* available. When using a capacity-restricted queue, this method is 
* generally preferable to {@link #add}, which can fail to insert an 
* element only by throwing an exception. 
* 
* @param e the element to add 
* @return {@code true} if the element was added to this queue, else 
*   {@code false} 
* @throws ClassCastException if the class of the specified element 
*   prevents it from being added to this queue 
* @throws NullPointerException if the specified element is null 
* @throws IllegalArgumentException if some property of the specified 
*   element prevents it from being added to this queue 
*/ 
boolean offer(E e); 

/** 
* Inserts the specified element into this queue, waiting if necessary 
* for space to become available. 
* 
* @param e the element to add 
* @throws InterruptedException if interrupted while waiting 
* @throws ClassCastException if the class of the specified element 
*   prevents it from being added to this queue 
* @throws NullPointerException if the specified element is null 
* @throws IllegalArgumentException if some property of the specified 
*   element prevents it from being added to this queue 
*/ 
void put(E e) throws InterruptedException; 

/** 
* Inserts the specified element into this queue, waiting up to the 
* specified wait time if necessary for space to become available. 
* 
* @param e the element to add 
* @param timeout how long to wait before giving up, in units of 
*  {@code unit} 
* @param unit a {@code TimeUnit} determining how to interpret the 
*  {@code timeout} parameter 
* @return {@code true} if successful, or {@code false} if 
*   the specified waiting time elapses before space is available 
* @throws InterruptedException if interrupted while waiting 
* @throws ClassCastException if the class of the specified element 
*   prevents it from being added to this queue 
* @throws NullPointerException if the specified element is null 
* @throws IllegalArgumentException if some property of the specified 
*   element prevents it from being added to this queue 
*/ 
boolean offer(E e, long timeout, TimeUnit unit) 
    throws InterruptedException; 

/** 
* Retrieves and removes the head of this queue, waiting if necessary 
* until an element becomes available. 
* 
* @return the head of this queue 
* @throws InterruptedException if interrupted while waiting 
*/ 
E take() throws InterruptedException; 

/** 
* Retrieves and removes the head of this queue, waiting up to the 
* specified wait time if necessary for an element to become available. 
* 
* @param timeout how long to wait before giving up, in units of 
*  {@code unit} 
* @param unit a {@code TimeUnit} determining how to interpret the 
*  {@code timeout} parameter 
* @return the head of this queue, or {@code null} if the 
*   specified waiting time elapses before an element is available 
* @throws InterruptedException if interrupted while waiting 
*/ 
E poll(long timeout, TimeUnit unit) 
    throws InterruptedException;