在生產者/消費者模型中,生產者Producer負責生產數據,而消費者Consumer負責使用數據。多個生產者線程會在同一時間運行,生產數據,並放到內存中一個共享的區域。期間,多個消費者線程讀取內存共享區,消費裏面的數據。
要求:
1. 針對上面的場景,請創建2個類,一個叫Producer,一個叫Consumer.
2. Producer類繼承Thread類,並實現把數據放到內存共享區的功能,這個功能要求是線程安全的。在個Producer類中的run方法中,循環20次,每次把一個整數放到內存共享區中。
3. Consumer類也繼承Thread類,並實現在沒有衝突的情況下,從內存共享區中獲取數據,並在標準輸出設備中打印輸出。輸出的格式爲:Consumer thread X retrieved integer Y.
4. 最後,創建一個main class,創建10個Procuder線程和4個消費者線程並啓動這些線程。
5. 要求有效代碼行數儘量少,最好不超過100行。
一. 消費者類
/** *//**
* 消費者類
* @author Amigo Xie([email protected])
*
*/
class Consumer extends Thread {
private Conn conn;
private int consumerNumber;
public Consumer(Conn conn1, int conNum) {
conn = conn1;
consumerNumber = conNum;
}
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("Consumer thread " + consumerNumber + " retrieved integer: " + conn.read()); //
try {
sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
* 消費者類
* @author Amigo Xie([email protected])
*
*/
class Consumer extends Thread {
private Conn conn;
private int consumerNumber;
public Consumer(Conn conn1, int conNum) {
conn = conn1;
consumerNumber = conNum;
}
public void run() {
for (int i = 0; i < 50; i++) {
System.out.println("Consumer thread " + consumerNumber + " retrieved integer: " + conn.read()); //
try {
sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
二. 生產者類
/** *//**
* 生產者類
* @author Amigo Xie([email protected])
*
*/
class Producer extends Thread {
private Conn conn;
public Producer(Conn conn1) {
conn = conn1;
}
public void run() {
for (int i = 0; i < 20; i++) {
conn.add(i);
}
}
}
* 生產者類
* @author Amigo Xie([email protected])
*
*/
class Producer extends Thread {
private Conn conn;
public Producer(Conn conn1) {
conn = conn1;
}
public void run() {
for (int i = 0; i < 20; i++) {
conn.add(i);
}
}
}
三. 線程通信類
/** *//**
* 線程通信類
* @author Amigo Xie([email protected])
*
*/
class Conn {
private int buffer[] = new int[200]; //10個Procuder線程,需存放200個變量
private int next = 0; //Flags to keep track of our int buffer status
private boolean isFull = false;
private boolean isEmpty = true;
/** *//**
* method to read int
* @return
*/
public synchronized int read() {
while (isEmpty == true) { //We can't read if there is nothing in our int buffer
try {
wait();//we'll exit this when isEmpty turns false
}catch (InterruptedException e) {
e.printStackTrace();
}
}
next--; //decrement the count,since we're going to read one int
if (next == 0) {
isEmpty = true; //Did we read the last letter?
}
isFull = false;
notify();
return (buffer[next]);//return the int to the thread that is reading
}
/** *//**
* method to add integer to the buffer
* @param number
*/
public synchronized void add(int number) {
while (isFull == true ) { //Wait around until there's room to add another letter
try {
wait();//This will exit when isFull turns false
}catch (InterruptedException e) {
e.printStackTrace();
}
}
next++; //add the integer to the next available spot buffer[next]=number;Change the next available spot
if (next == 200) {
isFull = true; //Are we full?
} else {
buffer[next] = number;
}
isEmpty =false;
notify();
}
}
* 線程通信類
* @author Amigo Xie([email protected])
*
*/
class Conn {
private int buffer[] = new int[200]; //10個Procuder線程,需存放200個變量
private int next = 0; //Flags to keep track of our int buffer status
private boolean isFull = false;
private boolean isEmpty = true;
/** *//**
* method to read int
* @return
*/
public synchronized int read() {
while (isEmpty == true) { //We can't read if there is nothing in our int buffer
try {
wait();//we'll exit this when isEmpty turns false
}catch (InterruptedException e) {
e.printStackTrace();
}
}
next--; //decrement the count,since we're going to read one int
if (next == 0) {
isEmpty = true; //Did we read the last letter?
}
isFull = false;
notify();
return (buffer[next]);//return the int to the thread that is reading
}
/** *//**
* method to add integer to the buffer
* @param number
*/
public synchronized void add(int number) {
while (isFull == true ) { //Wait around until there's room to add another letter
try {
wait();//This will exit when isFull turns false
}catch (InterruptedException e) {
e.printStackTrace();
}
}
next++; //add the integer to the next available spot buffer[next]=number;Change the next available spot
if (next == 200) {
isFull = true; //Are we full?
} else {
buffer[next] = number;
}
isEmpty =false;
notify();
}
}
四. 測試類
/** *//**
* 測試類
* @author Amigo Xie([email protected])
*
*/
public class ProducerAndConsumerTest {
/** *//**
* @param args
*/
public static void main(String[] args) {
Conn conn = new Conn();
Producer pro1 = new Producer(conn);
Producer pro2 = new Producer(conn);
Producer pro3 = new Producer(conn);
Producer pro4 = new Producer(conn);
Producer pro5 = new Producer(conn);
Producer pro6 = new Producer(conn);
Producer pro7 = new Producer(conn);
Producer pro8 = new Producer(conn);
Producer pro9 = new Producer(conn);
Producer pro10 = new Producer(conn);
Consumer consumer1 = new Consumer(conn, 1);
Consumer consumer2 = new Consumer(conn, 2);
Consumer consumer3 = new Consumer(conn, 3);
Consumer consumer4 = new Consumer(conn, 4);
pro1.start();
pro2.start();
pro3.start();
pro4.start();
pro5.start();
pro6.start();
pro7.start();
pro8.start();
pro9.start();
pro10.start();
consumer1.start();
consumer2.start();
consumer3.start();
consumer4.start();
}
* 測試類
* @author Amigo Xie([email protected])
*
*/
public class ProducerAndConsumerTest {
/** *//**
* @param args
*/
public static void main(String[] args) {
Conn conn = new Conn();
Producer pro1 = new Producer(conn);
Producer pro2 = new Producer(conn);
Producer pro3 = new Producer(conn);
Producer pro4 = new Producer(conn);
Producer pro5 = new Producer(conn);
Producer pro6 = new Producer(conn);
Producer pro7 = new Producer(conn);
Producer pro8 = new Producer(conn);
Producer pro9 = new Producer(conn);
Producer pro10 = new Producer(conn);
Consumer consumer1 = new Consumer(conn, 1);
Consumer consumer2 = new Consumer(conn, 2);
Consumer consumer3 = new Consumer(conn, 3);
Consumer consumer4 = new Consumer(conn, 4);
pro1.start();
pro2.start();
pro3.start();
pro4.start();
pro5.start();
pro6.start();
pro7.start();
pro8.start();
pro9.start();
pro10.start();
consumer1.start();
consumer2.start();
consumer3.start();
consumer4.start();
}