Domanda

Sto scrivendo un'applicazione Java che creerà un'istanza degli oggetti di una classe per rappresentare i client che si sono connessi e registrati con un sistema esterno sull'altro lato della mia applicazione.

Ogni oggetto client ha due classi nidificate al suo interno, che rappresentano il front-end e il back-end.la classe front-end riceverà continuamente i dati dal client reale e invierà indicazioni e dati alla classe back-end, che prenderà tali dati dal front-end e li invierà al sistema esterno utilizzando il formato e il protocollo appropriati quel sistema richiede.

Nella progettazione, cerchiamo di fare in modo che ogni istanziazione di un oggetto client sia un thread.Quindi, all'interno di ciascun thread ci saranno naturalmente due socket [EDIT]con i propri canali NIO ciascuno[/EDIT], uno lato client, uno lato sistema residente rispettivamente nel front-end e nel back-end.Tuttavia, questo ora introduce la necessità di socket non bloccanti.Ho letto il tutorial Qui che spiega come utilizzare in modo sicuro un selettore nel thread principale per gestire tutti i thread con connessioni.

Ma ciò di cui ho bisogno sono più selettori, ciascuno dei quali opera nel proprio thread.Dalla lettura del tutorial di cui sopra, ho appreso che i set di chiavi in ​​un selettore non sono thread-safe.Ciò significa che selettori separati istanziati nei rispettivi thread possono creare chiavi in ​​conflitto se provo a dare a ciascuno la propria coppia di socket e canali?Spostare il selettore sul thread principale è una piccola possibilità, ma tutt'altro che ideale in base ai requisiti software che mi sono stati forniti.Grazie per l'aiuto.

È stato utile?

Soluzione

Usare più selettori andrebbe bene purché non si registri lo stesso canale con gli stessi interessi (OP_READ / OP_WRITE ecc.) con entrambe le istanze del selettore.La registrazione dello stesso canale con più istanze di selettore potrebbe causare un problema in cui selector1.select() potrebbe consumare un evento a cui selector2.select() potrebbe essere interessato.

I selettori predefiniti sulla maggior parte delle piattaforme sono basati su poll() [o epoll()].

Selector.select chiama internamente il file int poll( ListPointer, Nfdsmsgs, Timeout) method.

        where the ListPointer structure can then be initialized as follows:

    list.fds[0].fd = file_descriptorA;
    list.fds[0].events = requested_events;
    list.msgs[0].msgid = message_id;
    list.msgs[0].events = requested_events;

Detto questo, consiglierei l'utilizzo di un singolo thread di selezione come menzionato nel tutorial di ROX RPC nio.Le implementazioni NIO dipendono dalla piattaforma ed è del tutto possibile che ciò che funziona su una piattaforma potrebbe non funzionare su un'altra.Ho riscontrato problemi anche nelle versioni minori.Ad esempio, AIX JDK 1.6 SR2 utilizzava un selettore basato su poll() - PollSelectorImpl e il corrispondente provider di selezione come PollSelectorProvider, il nostro server funzionava correttamente.Quando sono passato a AIX JDK 1.6 SR5, che utilizzava un selettore ottimizzato basato su interfaccia pollset (PollSetSelectorImpl), abbiamo riscontrato frequenti blocchi nel nostro server in select() e socketchannel.close().Uno dei motivi che vedo è che apriamo più selettori nella nostra applicazione (in contrapposizione a quello ideale del modello Selecting Thread) e l'implementazione di PollSetSelectorImpl come descritto Qui.

Altri suggerimenti

Se è necessario utilizzare questa connessione a socket singolo, è necessario separare il processo di ricezione e scrittura dei dati da e verso il canale dall'elaborazione dei dati stessi.Non è necessario delegare il canale.Il canale è come un autobus.Il bus (il thread singolo, che gestisce il canale) deve leggere i dati e scriverli in una coda di input (thread-safe) includendo le informazioni richieste, in modo che i thread client possano prelevare il pacchetto di datagrammi corretto da la fila.Se al thread client piace scrivere dati, tali dati vengono scritti in una coda di output che viene quindi letta dal thread del canale per scrivere i dati nel canale.

Quindi da un concetto di condivisione di una connessione tra attori che utilizzano questa connessione con i loro tempi di elaborazione imprevedibili (che è il motivo principale dei blocchi), si passa a un concetto di lettura dati, elaborazione e scrittura dati asincroni.Quindi non è più il tempo di elaborazione ad essere imprevedibile, ma il tempo in cui i tuoi dati vengono letti o scritti.Non bloccante significa che il flusso di dati è il più costante possibile, nonostante il tempo necessario per elaborarli.

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