2012-05-21 16 views
7

Esistono differenze tra un canale Go e un Java BlockingQueue? Entrambe sono code con una simile semantica di blocco e memoria. Opzionalmente entrambi possono avere un set di capacità.Go channel vs Java BlockingQueue

risposta

12

Direi che la più grande differenza è che i canali Go hanno il supporto per il select dichiarazione, che consentono di eseguire esattamente un funzionamento del canale. Un esempio (alterata dalla Go language specification):

select { 
case i1 = <-c1: 
    print("received ", i1, " from c1\n") 
case c2 <- i2: 
    print("sent ", i2, " to c2\n") 
case i3, ok := (<-c3): // same as: i3, ok := <-c3 
    if ok { 
     print("received ", i3, " from c3\n") 
    } else { 
     print("c3 is closed\n") 
    } 
} 

In questo esempio, esattamente una delle operazioni di ricezione-da-c1, invia-to-c2, o ricevere-da-c3 viene eseguita. Quando si entra nella selezione, un canale pronto (se presente) viene selezionato casualmente. Altrimenti, l'operazione si blocca fino a quando uno dei canali è pronto.

Non sono a conoscenza di alcun modo banale per modellare questa selezione di canali utilizzando le utilità Java. Si potrebbe sostenere che questa è una proprietà della dichiarazione select piuttosto che la progettazione di canali, ma direi che è fondamentale per la progettazione dei canali.

+1

Penso che potresti avvicinarti usando il metodo del sondaggio su una coda di blocco. Ma hai ragione che l'istruzione select fornisce supporto sintattico per il multiplexing su un numero di canali diversi. –

+1

Giusto, non ho parlato di busy-wait perché considero una non-soluzione :-). –

2

Possono essere utilizzati in modi simili.

  • Entrambi possono bloccare quando si inserisce/invia o si prende/riceve.
  • Entrambi hanno una capacità che governa quando l'invio verrà bloccato.

Le maggiori differenze sono probabilmente che i canali di go sono considerevolmente più economici di un oggetto java. e che i canali di go possono essere limitati a solo inviare o ricevere solo in grado di garantire alcune imposizioni di tipo aggiuntive per quanto riguarda chi può inviare e chi può ricevere da un canale.

+1

Hai qualche fonte per dimostrare che sono molto più economici? Non è che non ti creda, ma non sarei sorpreso se alcune delle code e dei canali nio di Java fossero in grado di tenere il passo dei tempi di esecuzione. Sono sicuro che Java si perde sul fronte della memoria però. –

+0

@AdamGent Ho paura di non avere risorse a portata di mano. Stavo principalmente parlando di memoria, ma non di velocità di esecuzione. –

3

Per fare qualcosa di simile all'istruzione golang'select in java si prevede l'utilizzo del pacchetto java.nio. Specificamente selettori e canali. Controlla la documentazione del pacchetto qui:

http://docs.oracle.com/javase/6/docs/api/java/nio/channels/package-summary.html#multiplex

offre praticamente la stessa capacità come l'istruzione select golang, utilizzando un singolo thread di multiplex lettura/scrittura da più canali.

+2

I canali Go consentono di trasferire strutture di dati arbitrarie (inclusi i puntatori), ma java.nio.channels consente solo il trasferimento dei byte. Non penso che siano davvero comparabili. –

5

Un'altra differenza molto importante è la seguente: è possibile chiudere un canale Go per segnalare che non vi sono più elementi in arrivo. Questo non è possibile usando Java.

Esempio: goroutine A legge un elenco di file. Pubblica ogni file nel canale. Dopo l'ultimo file, chiude il canale. goroutine B legge i file dal canale e li elabora in qualche modo. Dopo che il canale è stato chiuso, la goroutine si chiude.

Fare questo in Java non è facilmente possibile; tuttavia esistono alcuni soluzioni alternative.

+1

Davvero! Questa è una differenza molto importante. Con Java, devi inviare qualche tipo di record veleno o carattere di fine flusso per segnalare che non ci saranno altri elementi in arrivo. Ciò richiede codice aggiuntivo su entrambi i lati, vedi [javadoc di BlockingQueue] (https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html): 'una tattica comune è per i produttori di inserire oggetti speciali di fine flusso o veleno, che vengono interpretati di conseguenza quando vengono presi dai consumatori –