Reputation: 10023
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!
Upvotes: 1
Views: 2984
Reputation: 74750
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.
Upvotes: 1
Reputation: 13624
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();
}
Upvotes: 0
Reputation: 533510
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.
Upvotes: 1