2015-04-27 49 views
6

我在SO和Google上搜索了這個問題的答案,但到目前爲止找不到合適的解決方案。Java阻止列表實現

我目前正在一個圖形路由問題的LayerManager。經理負責提供和重置固定的一組圖層。

我想用阻塞列表實現Consumer-Producer模式,以便只要沒有空閒層可用,傳入的路由請求就會被阻塞。到目前爲止,我只發現了一個blocking queue,但由於我們不需要FIFO,LIFO但是隨機訪問一個隊列並不真正起作用。爲了更精確一些,應該可以這樣做:

有什麼辦法可以實現這個嗎?

+0

什麼java.util.concurrent.PriorityBlockingQueue中與自己的比較? – StanislavL

+0

謝謝。那麼,我認爲圖層並沒有真正的可比性。他們只匹配給定的請求。 –

回答

0

你在找什麼叫做「Semaphore」。

  1. 創建一個Semaphore類
  2. 添加它作爲一個字段層類


public class Semaphore 
{ 
    private boolean signal = false; 

    public synchronized boolean take() 
    { 
     if(this.signal==true) 
      return false; //already in use 
     this.signal = true; 
     this.notify(); 
     return true; 
    } 

    public synchronized void release() throws InterruptedException 
    { 
     while(!this.signal) wait(); 
     this.signal = false; 
    } 


    public boolean isUnused() 
    { 
     return !signal ; 
    } 

} 


//2. 
class Layer 
{ 
    Semaphore sem =null; 

    /*your code*/ 
    /*sem = new Semaphore(); in constructors*/ 
    public boolean take() 
    { 
     return this.sem.take(); 
    } 

    public void release() 
    { 
     this.sem.release(); 
    } 

    public Layer getLayer() 
    { 

     for (Layer layer : layers) 
     { 
     if (layer.matches(request) && layer.take()) 
      return layer; 
     } 

     return null; 
    } 
} 


同步方法處理訪問同意

3.遍歷getLayer直到

Layer l=null; 
while(l==null) 
{ 
    l= getlayer(); 
    Thread.sleep(100); //set time 
} 
// continue 
// do not forget to release the layer when you are done 
+1

這是我現在做的一種,我不喜歡這種通知/等待模式。它比阻止更容易出錯 –

0

嘗試使用Map<String, BlockingQueue<Layer>>。這個想法是保留BlockingQueue的免費圖層。每個請求都有自己的隊列。

public class LayerQueue { 

    Map<String, BlockingQueue<Layer>> freeLayers = Collections.synchronizedMap(new HashMap<String, BlockingQueue<Layer>>()); 

    public LayerQueue() { 
     //init QUEUEs 
     freeLayers.put("request-1", new ArrayBlockingQueue<Layer>(1)); // one to one... 
     freeLayers.put("request-2", new ArrayBlockingQueue<Layer>(1)); 
     [...] 
    } 

    public void addUnusedLayer(Layer layer, String request) { 
     BlockingQueue<Layer> freeLayersForRequest = freeLayers.get(request); 
     freeLayersForRequest.add(layer); 
    } 

    public Layer getLayer(String request) { 

     BlockingQueue<Layer> freeLayersForRequest = freeLayers.get(request); 

     try { 
      return freeLayersForRequest.take(); // blocks until a layer becomes available 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
     return null; 
    } 
} 
+0

1每個請求有一個圖層,地圖也不是固定大小 –

+0

@DanielGerber爲什麼它應該是一個問題? – dit

+0

因爲1層可能需要高達500MB的RAM。 –

0

我不太清楚我正確理解你的需求,但你可以消耗阻塞隊列,並把結果放到一個列表。如果在列表中找不到合適的圖層,請調用wait()並再次檢查何時將新項目從隊列添加到列表中。這聽起來像它可能在概念上工作,即使下面的代碼並沒有得到它的權利(我敢肯定這是不是很恰當同步)

public class PredicateBlockingQueue<Product> { 

private final List<Product> products = new LinkedList<Product>(); 
private final BlockingQueue<Product> queue; 
private final Thread consumer; 

public PredicateBlockingQueue(int capacity) { 
    queue = new ArrayBlockingQueue<Product>(capacity); 

    consumer = new Thread() { 
     @Override 
     public void run() { 
      while(!Thread.interrupted()) { 
       try { 
        products.add(queue.take()); 
        synchronized(queue) { 
         queue.notifyAll(); 
        } 
       } catch (InterruptedException e) { 
        e.printStackTrace(); 
       } 
      } 
     } 
    }; 

    consumer.start(); 
} 

public void put(Product product) throws InterruptedException { 
    queue.put(product); 
} 

public Product take(Predicate<Product> predicate) throws InterruptedException { 
    Product product; 
    while((product=find(predicate))==null) { 
     synchronized(queue) { 
      queue.wait(); 
     } 
    } 
    return product; 
} 

private synchronized Product find(Predicate<Product> predicate) { 
    Iterator<Product> it = products.iterator(); 
    while(it.hasNext()) { 
     Product product = it.next(); 
     if(predicate.test(product)) { 
      it.remove(); 
      return product; 
     } 
    } 
    return null; 
}