Java 阻止列表实现

问题描述 投票:0回答:3

我在SO和Google上搜索了这个问题的答案,但到目前为止找不到合适的解决方案。

我目前正在研究图形路由问题中的 LayerManager。管理器负责提供和重置一组固定的图层。

我想用阻止列表来实现消费者-生产者模式,这样只要没有可用的空闲层,传入的路由请求就会被阻止。到目前为止,我只找到了一个阻塞队列,但由于我们不需要先进先出、后进先出,但随机访问队列并没有真正起作用。更准确地说,这样的事情应该是可能的:

/* this should be blocking until a layer becomes available */
public Layer getLayer() { 
    for (Layer layer : layers) {
        if (layer.isUnused() && layer.matches(request))
            return layers.pop(layer);
    }
}

有什么办法可以实现这个目标吗?

java list graph blocking
3个回答
0
投票

你要找的东西叫做“信号量”。

  1. 创建信号量类
  2. 将其作为字段添加到 Layer 类

示例

 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

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
投票

我不太确定我是否正确理解了您的需求,但是您可以使用阻塞队列并将结果放入列表中。如果在列表中找不到适当的层,请调用 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.