views:

1088

answers:

3

Hi there, I'm writing a Java application that will instantiate objects of a class to represent clients that have connected and registered with an external system on the other side of my application.

Each client object has two nested classes within it, representing front-end and back-end. the front-end class will continuously receive data from the actual client, and send indications and data to the back-end class, which will take that data from the front-end and send it to the external system in using the proper format and protocol that system requires.

In the design, we're looking to have each instantiation of a client object be a thread. Then, within each thread will naturally be two sockets [EDIT]with their own NIO channels each[/EDIT], one client-side, one system-side residing in the front- and back-end respectively. However, this now introduces the need for nonblocking sockets. I have been reading the tutorial here that explains how to safely use a Selector in your main thread for handling all threads with connections.

But, what I need are multiple selectors--each operating in their own thread. From reading the aforementioned tutorial, I've learned that the key sets in a Selector are not threadsafe. Does this mean that separate Selectors instantiated in their own repsective threads may create conflicting keys if I try to give them each their own pair of sockets and channels? Moving the selector up to the main thread is a slight possibility, but far from ideal based on the software requirements I've been given. Thank you for your help.

+2  A: 

If you have to use this single socket connection, you have to separate the process of receiving and writing data from and to the channel from the data processing itself. You do not must delegate the channel. The channel is like a bus. The bus (the single thread, that manages the channel) has to read the data and to write it into a (thread-safe) input queue including the information required, so your client thread(s) can pick up the correct datagram package from the queue. If the client thread likes to write data, that data is written to an output queue which is then read by the channels thread to write the data to the channel.

So from a concept of sharing a connection between actors using this connection with their unpredictable processing time (which is the main reason for blocks), you move to a concept of asynchronous data read, data processing and data writing. So, it's not the processing time which is unpredictable anymore, but the time, your data is read or written. Non-blocking means, that the stream of data is as constant as possible, despite what time is required to process that data.

oeogijjowefi
I'm afraid I"m a little confused by your answer. Are you saying that a channel is in and of itself a thread, that a channel is its own thread, or that I should setup and poll the channels in a separate thread from the clients?I might not have been clear in my original post, each client object would have two sockets, and two channels for communicating on either side of the application. Having originally learned to write sockets in C, I'm familiar with the notion of non-blocking vs. non-blocking and specifically chose non-blocking because of a requirement for multiplexed communication.
bearcdp
This gonna be dicey so please, no down-votes ... the system issues swamp the discussion - see: http://www.ibm.com/developerworks/aix/library/au-pollset/index.html which gives a better answer. A channel is not designed as a Threading thingamabob: It is designed to operate in programming contexts where one wishes good io and threading performance. The entire issue is profoundly clouded by issues which are described in the Real-Time JSR ... the above link gives a discussion of the matter by engineers who are informed on the matter. I did some early testing, it is not as it seems.
Nicholas Jordan
+2  A: 

Using multiple selectors would be fine as long as you do not register the same channel with the same interests (OP_READ / OP_WRITE etc) with both the selector instances. Registering the same channel with multiple selector instances could cause a problem where selector1.select() could consume an event that selector2.select() could be interested in.

The default selectors on most of the platforms are poll() [or epoll()] based.

Selector.select internally calls the 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;

That said, I would recommend the usage of a single selecting thread as mentioned in the ROX RPC nio tutorial. NIO implementations are platform dependant, and it is quite possible that what works on one platform may not work on another. I have seen problems across minor versions too. For instance, AIX JDK 1.6 SR2 used a poll() based selector - PollSelectorImpl and the corresponding selector provider as PollSelectorProvider, our server ran fine. When I moved to AIX JDK 1.6 SR5, which used a pollset interface based optimized selector (PollSetSelectorImpl), we encountered frequent hangs in our server in the select() and socketchannel.close(). One reason I see is that we open multiple selectors in our application (as opposed to the ideal one Selecting Thread model) and the implementation of the PollSetSelectorImpl as described here.

Vijay
A: 

@Vijay: your issue is most likely resolved by http://www-01.ibm.com/support/docview.wss?uid=isg1fixinfo118020

chunnayya