Domanda

Il titolo di questa domanda mi fa dubitare che esista, ma comunque:

Sono interessato a sapere se esiste un implementato di Java BlockingQueue , che è delimitato da dimensioni e non si blocca mai, ma piuttosto genera un'eccezione quando si tenta di accodare troppi elementi.

Modifica - Sto passando BlockingQueue a un Executor, che suppongo usi il suo metodo add (), non offer (). Si può scrivere un BlockingQueue che avvolge un altro BlockingQueue e delegare le chiamate a add () to offer ().

È stato utile?

Soluzione

Modifica: in base alla tua nuova descrizione, credo che tu stia facendo la domanda sbagliata. Se stai usando un Executor dovresti probabilmente definire un RejectedExecutionHandler anziché modificare la coda. Funziona solo se stai usando un ThreadPoolExecutor, ma se non lo sei probabilmente sarebbe una buona idea modificare Executor piuttosto che la coda.

Ritengo che sia un errore ignorare l'offerta e farla comportare come aggiungere. I metodi di interfaccia costituiscono un contratto. Il codice client che utilizza le code di blocco dipende dai metodi che stanno effettivamente facendo ciò che la documentazione specifica. Infrangere quella regola si apre a un mondo di dolore. Quello, ed è inelegante.


Il add () su BlockingQueues lo fa, ma hanno anche un offer () che è generalmente una scelta migliore. Dalla documentazione per offer ():

  

Inserisce l'elemento specificato in   coda di questa coda se è possibile   per farlo immediatamente senza eccedere   la capacità della coda, ritornando vera   in caso di successo e falso se questa coda   è pieno. Questo metodo è generalmente   preferibile al metodo aggiungere (E), che può   non riesce a inserire un elemento solo da   generare un'eccezione.

Funziona con tutte queste code indipendentemente dall'implementazione specifica (ArrayBlockingQueue, LinkedBlockingQueue ecc.)

BlockingQueue<String> q = new LinkedBlockingQueue<String>(2);
System.out.println(q.offer("foo")); // true
System.out.println(q.offer("bar")); // true
System.out.println(q.offer("baz")); // false

Altri suggerimenti

  

Si può scrivere una BlockingQueue   avvolge un altro BlockingQueue e   delega le chiamate a add () to offer ().

Se questa dovrebbe essere una domanda ... la risposta è " Sì " ;, ma puoi farlo più ordinatamente creando una sottoclasse che sovrascrive add (). L'unico problema (in entrambi i casi) è che la tua versione di aggiungi non può generare eccezioni verificate che non sono nel metodo che stai sovrascrivendo, quindi il tuo " bloccherebbe " l'eccezione dovrà essere deselezionata.

questo è triste, non puoi bloccare, ci sono così tanti casi d'uso in cui vorresti bloccare, l'idea di fornire la tua coda di blocco limitata all'esecutore non ha alcun significato.

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)) {
            if (runState == RUNNING && workQueue.***offer***(command)) {
                if (runState != RUNNING || poolSize == 0)
                    ensureQueuedTaskHandled(command);
            }
            else if (!addIfUnderMaximumPoolSize(command))
                reject(command); // is shutdown or saturated
        }
    }

Un semplice caso d'uso per ottenere query eseguite dal db di origine in batch (esecutore), arricchire in batch e inserirle in un altro db (esecutore), si vorrebbe eseguire query solo velocemente quanto vengono inserite in un altro db. In tal caso, l'esecutore dest dovrebbe accettare un esecutore limitato al blocco per risolvere il problema piuttosto che continuare il polling e controllare quanti sono stati completati per eseguire più query.

Oops di più, vedi il mio commento residuo:

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top