我在SO和Google上搜索了這個問題的答案,但到目前爲止找不到合適的解決方案。Java阻止列表實現
我目前正在一個圖形路由問題的LayerManager。經理負責提供和重置固定的一組圖層。
我想用阻塞列表實現Consumer-Producer模式,以便只要沒有空閒層可用,傳入的路由請求就會被阻塞。到目前爲止,我只發現了一個blocking queue,但由於我們不需要FIFO,LIFO但是隨機訪問一個隊列並不真正起作用。爲了更精確一些,應該可以這樣做:
有什麼辦法可以實現這個嗎?
我在SO和Google上搜索了這個問題的答案,但到目前爲止找不到合適的解決方案。Java阻止列表實現
我目前正在一個圖形路由問題的LayerManager。經理負責提供和重置固定的一組圖層。
我想用阻塞列表實現Consumer-Producer模式,以便只要沒有空閒層可用,傳入的路由請求就會被阻塞。到目前爲止,我只發現了一個blocking queue,但由於我們不需要FIFO,LIFO但是隨機訪問一個隊列並不真正起作用。爲了更精確一些,應該可以這樣做:
有什麼辦法可以實現這個嗎?
你在找什麼叫做「Semaphore」。
例
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
這是我現在做的一種,我不喜歡這種通知/等待模式。它比阻止更容易出錯 –
嘗試使用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;
}
}
我不太清楚我正確理解你的需求,但你可以消耗阻塞隊列,並把結果放到一個列表。如果在列表中找不到合適的圖層,請調用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;
}
什麼java.util.concurrent.PriorityBlockingQueue中與自己的比較? – StanislavL
謝謝。那麼,我認爲圖層並沒有真正的可比性。他們只匹配給定的請求。 –