2017-01-31 1 views
0

synchrone Je travaille avec une lib externe qui définit une classe Monitor qui accepte une interface Sensor et envoie les résultats en périodiquement:Java8 - Conversion d'une interface asynchrone en une

public interface Sensor { 
    // called by the monitor when new results are available 
    void updatedResult(double result); 

    // called when done sending results 
    void done(); 
} 

J'ai mis en place le capteur suit:

public class SensorImpl implements Sensor { 
    private boolean isDone; 
    private List<double> data; 

    public SensorImpl() { 
     this.isDone = false; 
     this.data = new ArrayList<>(); 
    } 

    @Override 
    void updatedResult(double result); 
     this.data.add(result); 
    } 

    @Override 
    void done() { 
     this.isDone = true; 
    } 

    public boolean isDoneReceiving() { 
     return this.isDone; 
    } 

    public List<double> getData() { 
     return this.data; 
    } 
} 

Et je suis en cours d'exécution de mon programme comme celui-ci (simplifié):

public void run() { 

    // initialize a sensor instance 
    SensorImpl sensor = new SensorImpl(); 

    // initialize a monitor that streams data into the sensor (async) 
    Monitor monitor = new Monitor(sensor); 

    // start monitoring the sensor 
    monitor.start(); 

    // block until done 
    while (!sensor.isDoneReceiving()) { 
     Thread.sleep(50); 
    } 

    // retrieve data and continue processing... 
    List<double> data = sensor.getData(); 

    // ... 
} 

Alors que cela fonctionne, il semble icky de bloquer sur un fil avec le sommeil, et je suis à la recherche d'un moyen de rendre cela plus propre. Cela devient encore plus pertinent lors de l'application d'exécuteurs pour surveiller plusieurs capteurs de différents types en parallèle. Toute aide sera appréciée.

MISE À JOUR:

J'ai fini par mettre en œuvre Future<List<Double>>, ce qui m'a permis d'appeler simplement List<Double> results = sensor.get();, qui bloque jusqu'à ce que tous les résultats sont disponibles.

public class SensorImpl implements Sensor { 

    // ... 
    private CountDownLatch countDownLatch; 

    public SensorImpl() { 
     this.countDownLatch = new CountDownLatch(1); 
    } 

    // ... 

    @Override 
    public void done() { 
     // when called by async processes, decrement the latch (and release it) 
     this.countDownLatch.countDown(); 
    } 

    // ... 

} 

Voici une grande réponse qui a fourni une bonne référence: https://stackoverflow.com/a/2180534/187907

+2

votre fichier '' la mise en œuvre de done' countDown' un 'CountDownLatch' 1. Faites votre' 'la mise en œuvre isDoneReceiving' await' sur ce même' CountDownLatch '. –

Répondre

1

Dans votre cas, plusieurs classes du package concurrent peuvent vous aider, comme Semaphore, CoundDownLatch, CyclicBarrier ou même un BlockingQueue, où vous le feriez bloquez la file d'attente et attendez que les autres threads y mettent des valeurs lorsque vous avez terminé.

Un CountDownLatch est probablement le mieux adapté à votre exemple spécifique. Peut-être que vous pouvez voir this question, il a une belle vue d'ensemble sur les Sémaphore et CountDownLatch: