0
votes

I'm working on a Java client/server application with a pretty specific set of rules as to how I have to develop it. The server creates a ClientHandler instance that has input and output streams to the client socket, and any input and output between them is triggered by events in the client GUI.

I have now added in functionality server-side that will send out periodic updates to all connected clients (done by storing each created PrintWriter object from the ClientHandlers in an ArrayList<PrintWriter>). I need an equivalent mechanism client-side to process these messages, and have been told this needs to happen in a second client-side thread whose run() method uses a do...while(true) loop until the client disconnects.

This all makes sense to me so far, what I am struggling with is the fact that the two threads will have to share the one input stream, and essentially 'ignore' any messages that aren't of the type that they handle. In my head, it should look something like this:

Assuming that every message from server sends a boolean of value true on a message-to-all, and one of value false on a message to an individual client...

Existing Client Thread
//method called from actionPerformed(ActionEvent e)
//handles server response to bid request
public void receiveResponse()
{
    //thread should only process to-specific-client messages
    if (networkInput.nextBoolean() == false)
    {
        //process server response...
    }
}


Second Client-side Thread
//should handle all messages set to all clients
run()
{
    do {
        if (networkInput.nextBoolean() == true)
        {
            //process broadcasted message...
        } while (true);
}

As they need to use the same input stream, I would obviously be adding some synchronized, wait/notify calls, but generally, is what I'm looking to do here possible? Or will the two threads trying to read in from the same input stream interfere with each other too much?

Please let me know what you think!

Thanks, Mark

1
InputStream isn't thread safe; while possible with synchronization I would try to avoid it.Elliott Frisch
It's initialised as a Scanner(socket.getInputStream()), is that just as bad? I don't love the way it's structured but I can't see another way around it as I've been told the Client-side processing has to be done in two separate threads. Any alternatives you know of that I'm missing? @ElliottFrischmarcuthh
A Stream must be read by a single thread unless you can determine the destination before you read that boolean, which is clearly not what the spec says. - Use one thread to read the stream and... well Peter has it down pat...laune

1 Answers

2
votes

You can do it, though it will be complicated to test and get right. How much is "too much" depends on you. A simpler solution is to have a reader thread pass messages to the two worker threads.

ExecutorService thread1 = Executors.newSingleThreadedExecutors();
ExecutorService thread2 = Executors.newSingleThreadedExecutors();
while(running) {
    Message message = input.readMessage();
    if (message.isTypeOne())
        thread1.submit(() -> process(message));
    else if (message.isTypeTwo())
        thread2.submit(() -> process(message));
    else
        // do something else.
}
thread1.shutdown();
thread2.shutdown();