2015-07-24 22 views
6

Quando si utilizza BlockingQueue per consumare i dati prodotti, qual è il metodo più efficiente per attendere che i dati vengano visualizzati?Java: thread consumer consumer qual è il modo più efficiente per attendere la produzione dei dati

Scenario:

Passo lista 1) I dati sarà un archivio dati in cui vengono aggiunti timestamp a. Questi timestamp devono essere ordinati in base alla priorità temporale più vicina. Questa lista potrebbe essere vuota. Un thread inserirà il timestamp in esso. Produrre

Punto 2) Voglio consumare i dati in qui in un altro thread che porterà i timestamp dai dati e verificare se sono dopo il tempo corrente. consumatori poi Produce

Fase 3) Se sono dopo l'ora attuale poi inviarli a un altro thread per essere consumati e trasformati. Una volta che i dati del timestamp vengono elaborati qui, rimuovi dall'archivio dati del passaggio 1. Consumare quindi modificare l'elenco originale.

Nel seguente codice il campo dati si riferisce all'archivio dati nel passaggio 1. Il risultato è l'elenco di timestamp che sono stati inviati dopo l'ora corrente. Fase 2. I risultati verrà poi consumato passo 3.

private BlockingQueue<LocalTime> data; 
private final LinkedBlockingQueue<Result> results = new LinkedBlockingQueue<Result>(); 

@Override 
public void run() { 
    while (!data.isEmpty()) { 
    for (LocalTime dataTime : data) { 
     if (new LocalTime().isAfter(dataTime)) { 
     results.put(result); 
     } 
    } 
    } 
} 

Domande Qual è il modo più efficace per attendere i dati da aggiungere nella lista di dati che potrebbero essere potenzialmente vuoto? Focus on:

while (!data.isEmpty()) 

seguito da una precedente question.

+2

Utilizzare 'data.take()! = Null'. La chiamata 'isEmpty' è non-bloccante. – CKing

+1

Sì, beh, che senso ha usare una coda di blocco se la stai sondando? –

+0

Il tuo codice dice '! Data.isEmpty()' che significa che stai eseguendo il ciclo fino a ** ci sono alcuni dati ** nella tua lista di dati (in attesa che i dati vengano consumati). Ma il tuo requisito dice: "* aspetta ** i dati da aggiungere ** nella lista dei dati che potrebbero essere potenzialmente vuoti *." Qual è il tuo requisito qui? – hagrawal

risposta

5

qual è il modo più efficace per attendere i dati da produrre funzionalità

Il BlockingQueue ha il blocco che sarà sospendere le discussioni in attesa perché una coda non sia vuota o non piena. Nel tuo caso stai girando sulla coda che consuma CPU. Questo non è preferito.

È necessario utilizzare take.

Sospensione recupera e rimuove il capo di questa coda, in attesa, se necessario, fino a quando un elemento diventa disponibile.

BlockingQueue#take

Questo sarà il modo più efficiente per attendere elementi di una coda come fili di sospensione non consumano CPU. Una volta che un nuovo oggetto viene messo in coda, i thread in attesa verranno risvegliati.

Quindi è possibile utilizzare put che ha la stessa semantica di attesa di take ma solo se la coda non è piena.

public void run(){ 
    LocalTime timestamp = null; 
    while((timestamp = data.take()) != null){ 
     ... 
    } 
} 

Aggiornamento in base alle nostre osservazioni:

Ma in questo caso si creano i timestamp in un ordine sequenziale e aggiunto. Ma un timestamp potrebbe essere inferiore in futuro. Per esempio. nodo principale è di 2 minuti in futuro, secondo nodo è 1 minuto, in modo che il secondo nodo vuole elaborazione prima

Poi il mio follow-up:

quindi è necessario priorità accodamento in base alla data e ora di il LocalDate?

Non sono sicuro se si sta utilizzando LocalDate da JodaTime o Java 8, assumiamo quest'ultimo.

È possibile utilizzare uno PriorityBlockingQueue con la stessa semantica di blocco. Tuttavia, l'aspetto prioritario di BlockingQueue accoderà gli elementi in base a qualsiasi ordine definito. Nel tuo caso, utilizzando LocalDate puoi avere elementi ordinati dal più vecchio al più giovane o dal più giovane al più vecchio.

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(); 

OR INVERSE THE ORDER 

BlockingQueue<LocalDate> data = new PriorityBlockingQueue<>(0, (a,b) -> b.compareTo(a)); 

In questo caso, si elaborare LocalDate nel loro ordine naturale e non l'ordine in cui sono accodati.

Se si utilizza il LocalDate di JodaTime, potrebbe essere necessario implementare il proprio Comparator simile al mio secondo esempio.

MODIFICA: ho appena realizzato di avere taggato come java-7. Quindi utilizzerai JodaTime e se il LocalDate di JodaTime non implementa Comparable, creane uno tuo.

+0

Grazie Penso che nel mio caso ora guardarlo utilizzando data.peek() è più appropriato in quanto il primo nodo non è necessariamente quello che vuole essere elaborato. – Matt

+0

Solo curioso, perché il primo nodo non dovrebbe essere elaborato? –

+0

Penso che molto probabilmente sarà accettato in senso generale. Ma in questo caso i timestamp vengono creati in ordine sequenziale e aggiunti. Ma un timestamp potrebbe essere inferiore in futuro. Per esempio. Il nodo principale è in futuro di 2 minuti, il secondo nodo è di 1 minuto, quindi il secondo nodo richiede l'elaborazione per primo. – Matt

0

Per utilizzare è necessario utilizzare il metodo take. Questo metodo si bloccherà mentre la coda è vuota. Questo sostituirà il tuo assegno per vedere se la coda è vuota.

In secondo luogo, perché è necessario un timestamp? Se il timestamp deve assicurarsi di elaborare le richieste nell'ordine in cui sono state inserite nella coda, non è necessario, poiché la coda è FIFO e creata per un ambiente multithread simultaneo. Se il timestamp proviene dall'esterno del sistema, qualche timestamp esterno, in cui le richieste potrebbero venire fuori ordine ma devono essere elaborate in ordine, questo BlockQueue non lo taglierà. Potrebbe essere necessario un PriorityBlockingQueue in cui verrà data la priorità alle richieste per data/ora. Quindi, elimina il timestamp o usa un PriorityBlockingQueue.

Problemi correlati