|
| |
Here's an example of a Producer
and a Consumer class, with a SharedBuffer class that provides
the necessary coordination between the two threads:
package threads;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* This is a Producer thread that supplies strings
* to a Consumer thread. It reads a line from System.in
* and passes it to the Consumer through a SharedBuffer,
* until the end of stream occurs.
*/
public class Producer extends Thread
{
public static void main(String[] args)
{
// Create a shared buffer
SharedBuffer buffer = new SharedBuffer();
// Create and start a consumer thread
Consumer consumer = new Consumer(buffer);
consumer.start();
// Create and start a Producer thread
Producer producer = new Producer(buffer);
producer.start();
}
Producer(SharedBuffer buffer)
{
super("Producer");
m_buffer = buffer;
}
public void run()
{
// Connect up to System.in
BufferedReader reader = new BufferedReader(
new InputStreamReader(System.in)
);
try
{
// Loop, asking for input from the user until EOF
while (true)
{
String line = reader.readLine();
if (line == null)
break; // End of input
m_buffer.putData(line);
}
}
catch (IOException e)
{
e.printStackTrace();
}
System.out.println("Done with input: Signalling to Consumer");
m_buffer.putData(null);
}
/// Private data ///
private SharedBuffer m_buffer;
}
/**
* This is a Consumer thread that waits for input from
* the Producer, supplied through a SharedBuffer. It
* accepts the string passed, reverses it, and prints out
* the result. When it encounters a null string, the thread
* exits.
*/
class Consumer extends Thread
{
Consumer(SharedBuffer buffer)
{
super("Consumer");
m_buffer = buffer;
}
public void run()
{
while (true)
{
String line = m_buffer.getData();
if (line == null)
break;
// Reverse the line and print it out
line = reverse(line);
System.out.println(line);
}
System.out.println("Consumer thread exiting...");
}
private String reverse(String string)
{
StringBuffer buffer = new StringBuffer(string);
return buffer.reverse().toString();
}
//// Private data ////
private SharedBuffer m_buffer;
}
/**
* This is a SharedBuffer class to which the Producer puts
* data, and from which the Consumer retrieves it.
* It contains the necessary thread coordination code to
* ensure that the Producer and Consumer work together properly.
*/
class SharedBuffer
{
static final int RESOURCE_LIMIT = 10;
boolean isFull()
{
return m_data.size() > RESOURCE_LIMIT;
}
boolean isEmpty()
{
return m_data.size() <= 0;
}
synchronized void putData(String s)
{
while ( isFull() ) // Wait until there's room
{
try
{
wait();
}
catch (InterruptedException e)
{
// Ignore
}
}
m_data.add(s); // To the end of the FIFO list
notify(); // Notify any waiter
}
synchronized String getData()
{
while ( isEmpty() ) // Wait until there's data available
{
try
{
wait();
}
catch (InterruptedException e)
{
// Ignore
}
}
String data = (String)(m_data.get(0)); // Get first element
if (data != null)
m_data.remove(data); // and remove it from the List
notify(); // Notify any waiter
return data;
}
//// Private data ////
// A list of strings.
private List<String> m_data = new ArrayList<String>();
private boolean m_done = false;
}
|
Here's a simple example of one run of this program:
Hello!
!olleH
How are you?
?uoy era woH
Nice talking to you!
!uoy ot gniklat eciN
Goodbye
eybdooG
Done with input: Signalling to Consumer
Consumer thread exiting...
|