I nodi di elaborazione dei messaggi ed i programmi di analisi devono operare in un ambiente a più thread e più istanze. Possono essere presenti molti oggetti nodi o programmi di analisi, ognuno con molti elementi di sintassi, e possono essere presenti molti thread che eseguono metodi su tali oggetti. La struttura del broker dei messaggi assicura che un oggetto messaggio e gli eventuali oggetti di sua proprietà vengano utilizzati solo dal thread che riceve ed elabora il messaggio attraverso il flusso di messaggi.
Un'istanza di un nodo di elaborazione del flusso di messaggi viene condiviso ed utilizzato da tutti i thread che servono il flusso di messaggi in cui è definito il nodo. Relativamente ai programmi di analisi, un'istanza di un programma di analisi viene utilizzata solo da un unico thread di flusso di messaggi.
Un'estensione definita da un utente deve aderire a tale modello e deve evitare l'uso di dati globali o risorse che richiedono semafori per serializzare l'accesso ai thread. Tale serializzazione può risultare in colli di bottiglia delle prestazioni.
Le funzioni di implementazione dell'estensione definita dall'utente devono essere rientranti e così anche le eventuali funzioni che queste richiamano. Tutte le funzioni di utilità dell'estensione definita dall'utente sono completamente rientranti.
Sebbene un'estensione definita dall'utente può produrre ulteriori thread se richiesto, è essenziale che lo stesso thread restituisca il controllo al broker al completamento di una funzione di implementazione. Nell'eventualità si verifichi un malfunzionamento nell'esecuzione di ciò, verrà compromessa l'integrità del broker e si verificheranno dei risultati imprevedibili.
L'esempio di flusso di messaggi riportato di seguito risulta utile nella comprensione di alcune delle considerazioni di thread che devono essere tenute presenti quando di progettano e implementano propri nodi definiti dall'utente. Viene considerato l'esempio di un nodo di input definito dall'utente.
E' possibile configurare un flusso di messaggi da eseguire su una serie di thread. Ciò è determinato dal numero di nodi di input nel flusso di messaggi e dal valore della proprietà additionalInstances del flusso di messaggi. Questi due elementi determinano la capacità massima del pool di thread che il flusso di messaggi può utilizzare. Quindi, se il flusso di messaggi ha determinati requisiti di elaborazione che richiedono l'esecuzione di un singolo thread, è necessario assicurare che questo sia il caso.
Il modo più efficace per impedire alla coda di input di diventare un collo di bottiglia consiste nel consentire al broker di avviare ulteriori copie del flusso di messaggi in thread separati utilizzando la proprietà additionalInstances. Tuttavia, la creazione di thread separati consente l'elaborazione parallela di messaggi dal gestore code, cosicché è necessario utilizzare solo questa proprietà quando l'ordine di elaborazione dei messaggi non è importante.
I thread vengono creati come risultato del funzionamento e della creazione del nodo di input. Un thread rimane attivo o inattivo nel pool di thread e i thread inattivi rimangono nel pool finché non vengono inviati da un nodo di input o il broker non viene chiuso.
La figura riportata di seguito mostra l'assegnazione di thread in un flusso di messaggi.
Assegnazione di thread in un flusso di messaggi
Inizialmente, viene eseguita una domanda al Thread 1 (A) quindi attende messaggi. Quando arriva un messaggio (B), il Thread 1 propaga il messaggio e invia il Thread 2. Il Thread 2 riceve immediatamente un messaggio (C) e propaga e invia il Thread 3, che attende un messaggio (D). Il Thread 1 termina (E) e torna al pool di thread. Il Thread 3 riceve quindi un messaggio (F), invia il Thread 1 e propaga il messaggio. Il Thread 1 attende quindi l'arrivo di un messaggio sulla coda (G).
Degno di nota è il punto contrassegnato con H. A questa istanza nel flusso di messaggi, il Thread 1 acquisisce un messaggio, ma poiché tutti gli altri thread sono attivi in quel momento, non può eseguire l'invio. Il messaggio viene propagato.
Dopo che questo messaggio è stato propagato, il Thread 2 termina (I), riceve un nuovo messaggio dalla coda e ne esegue la propagazione. Il Thread 3 quindi termina (J) e torna al pool. Quindi anche il Thread 2 termina (K). Poiché non ha eseguito l'invio, quando il Thread 1 termina (L), non può tornare al pool di thread anche se non ci sono messaggi nella coda; attende quindi l'arrivo di un messaggio sulla coda.