1

I would like to know what is in your opinion the best way of implementing a program where two threads are exchanging Strings and responding to each other.

I couldn't get it to work, either with java.nio.Pipe and java.io.PipedInputStream / java.io.PipedOutput.Stream

Here is a code example of what I want to do:

The main class, setting everything up.

public static void main(String[] args) {
        // TODO
        // Create two communication channel, and bind them together

        MyThread t1 = new MyThread(channel1Reader, channel2Writer, 0);
        MyThread t2 = new MyThread(channel2Reader, channel1Writer, 1);

        t1.run();
        t2.run();

    }

The thread class:

public class MyThread extends Thread {
    private ? inputStream;
    private ? outputStream;
    private boolean canTalk;
    private int id;

    public MyThread(? inputStream, ? outputStream, boolean isStarting, int id) {
        this.inputStream = inputStream;
        this.outputStream = outputStream;
        this.canTalk = isStarting;
        this.id = id;
    }

    public void run() {
        while(true) {
            if(canTalk) {
                String s = getRandomWord();
                // TODO
                // Write s to the output stream
            }

            // TODO
            // Wait until receiving a String on the input stream
            String s2 = the word I just received
            Log.info("Thread " + id + " received the word '" + s2 + "'");
            canTalk = true;
            Thread.sleep(1000);
        }
    }

Any ideas?

Thanks!

1
  • as a general side note, if you find yourself using "Thread.sleep" when writing multi-threaded code, you are most likely doing it wrong. Commented Mar 16, 2011 at 16:52

3 Answers 3

1

PipedInout/OutputStream are useful if you have a library which has to take an input/output stream. Otherwise is one of the least friendly ways to exchange data between threads.

However, the simplest way to exchange data between threads is to use an ExecutorService. You can submit Callable<String> tasks to the service and get results from Future<String>

Another approach is to use multiple BlockingQueue<String> but this doesn't save much and lacks the functionality an ExecutorService gives you.

The problem you have with your example is it is much simpler to implement as a single thread. I suggest you look at functionality which is best performed by multiple threads.

Sign up to request clarification or add additional context in comments.

Comments

1

You are using here

    t1.run();
    t2.run();

This executes the run methods of both Thread objects in the current thread, and one after the other. The threads constructed are not actually started.

This way the communication can't work, since the reading thread is not yet started when the writing thread writes, and the other way around. User

    t1.start();
    t2.start();

here, or use a ThreadPool with Runnable objects, instead of Thread subclasses.

1 Comment

Good catch, I completely missed that.
0

I usually use a Queue, likely backed by a LinkedList.

To read:

synchronized (q) {
    while (q.isEmpty() && !stopSignal) {
        q.wait(3000);
    }
    return q.poll();
}

To write:

synchronized (q) {
    q.add(item);
    q.notify();
}

2 Comments

Or use BlockingQueue. You are basically trying to implement one yourself when it is already in java.concurrent.
I have found that, to make BlockingQueue work appropriately, you need to interrupt your thread when you want it to stop blocking. The only reason I would use a BlockingQueue is if I had to limit the number of items allowed in the queue at once. To make it work properly in this situation requires just as much code as I have posted here, plus adding a Thread.interrupt() call somewhere.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.