Implement Java Block List

I was looking for the answer to this question about SO and Google, but have not yet found a suitable solution.

I am currently working on a LayerManager in the graph routing problem. The manager is responsible for providing and resetting a fixed set of layers.

I wanted to implement a Consumer-Producer pattern with a block list so that incoming routing requests were blocked, since there is still no free level. So far I have found a blocking queue , but since we donโ€™t need FIFO, LIFO, but random access to the queue does not really work. To be more precise, something like this should be possible:

/* 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); } } 

Is there any way to achieve this?

+6
source share
3 answers

What you are looking for is called "Semaphore."

  • Create a Semaphore class
  • Add it as a field to the Layer class

Example

  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; } } 


Synchronized methods handle access negotiation

3. Scroll getLayer to

 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
source

Try using Map<String, BlockingQueue<Layer>> . The idea is to hold free layers inside a BlockingQueue . Each request has its own queue.

 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
source

I'm not quite sure I understand your need correctly, but you can use a blocking queue and put the results in a list. If the corresponding layer is not found in the list, call wait () and check again when a new item is added to the list from the queue. It seems like this can work conceptually, even if the code below does not fit (I'm sure it is not perfectly synchronized correctly)

 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; } 
0
source

Source: https://habr.com/ru/post/986036/


All Articles