筆試的題目類似地:一個生產者一次生產10個,滿了后通知消費者,然后等待。一個消費者產品有滿了就消費。到空時通知生產者,然后等待。
那時對等待/通知機制沒怎么寫過,那次筆試應該寫的大概對(想法對),但寫的wait()和notifyAll()的位置不對。現(xiàn)在有時間就寫了這個例子。
描述:生產者一次生產N個產品,池中達到M就等待,通知等待的消費者。消費者有產品就消費,到沒有時就通知生產者,然后等待。
1.生產者:
package net.blogjava.chenlb.multithreaded;
import java.util.List;
/**
* @author chenlb
*
* 生產者.<br/>
* 默認產品池大小M=20,產品梯階大小N=5.在生產過程中,池的大小會超過20,但池中最大應該是M+N-1.
*/
public class Producer implements Runnable {
/**
* 池默認大小
*/
public static final int DEFALUT_SIZE = 20;
/**
* 默認一次生產的數(shù)量
*/
public static final int DEFALUT_STEP_SIZE = 5;
private static int PRODUCER_ID = 0; //生產者號
private List<Product> pool = null;
private int size = DEFALUT_SIZE;
private int stepSize = DEFALUT_STEP_SIZE;
private String name = "Producer_"+(++PRODUCER_ID); //生產者名
private boolean isRun = true;
/**
* 默認產品池大小20, 默認產品增長梯階大小5
*/
public Producer(List<Product> pool) {
this.pool = pool;
}
/**
* @param pool
* @param size 池大小
*/
public Producer(List<Product> pool, int size) {
this.pool = pool;
this.size = size;
}
/**
* @param pool
* @param size 池大小
* @param stepSize 一次生產多少
*/
public Producer(List<Product> pool, int size, int stepSize) {
this.pool = pool;
this.size = size;
this.stepSize = stepSize;
}
public void run() {
// TODO 生產者線程
//int pi = 0;
while(isRun) {//&& pi<10
//pi++;
synchronized (pool) { //同步產品池
if(pool.size() >= size) {
try {
System.out.println(name+" 等待!");
pool.wait(); //同步什么就等待什么,否則拋出java.lang.IllegalMonitorStateException
} catch (InterruptedException e) {
isRun = false;
System.out.println(name+" thread interrupt!");
}
} else {
for(int i=0; i<stepSize; i++) { //一次生產stepSize個產品
pool.add(product()); //生產產品
}
System.out.println("產品池中有: "+pool.size());
pool.notifyAll(); //通知等待的線程(主要用來通知消費者, 但生產者線程也會通知到)
}
}
try {
System.out.println(name+" 休息1秒!");
Thread.sleep(1000); //調試用
} catch (InterruptedException e) {
System.out.println(name+" sleep 1s thread interrupt");
}
}
System.out.println(name+" end! pool size: "+pool.size());
}
private static int P_ID = 0;
/**
* 生產產品
* @return 產品
*/
private Product product() {
String name = "product_"+(++P_ID);
System.out.println(this.name+" 生產了: "+name);
return new Production(name);
}
}
import java.util.List;
/**
* @author chenlb
*
* 生產者.<br/>
* 默認產品池大小M=20,產品梯階大小N=5.在生產過程中,池的大小會超過20,但池中最大應該是M+N-1.
*/
public class Producer implements Runnable {
/**
* 池默認大小
*/
public static final int DEFALUT_SIZE = 20;
/**
* 默認一次生產的數(shù)量
*/
public static final int DEFALUT_STEP_SIZE = 5;
private static int PRODUCER_ID = 0; //生產者號
private List<Product> pool = null;
private int size = DEFALUT_SIZE;
private int stepSize = DEFALUT_STEP_SIZE;
private String name = "Producer_"+(++PRODUCER_ID); //生產者名
private boolean isRun = true;
/**
* 默認產品池大小20, 默認產品增長梯階大小5
*/
public Producer(List<Product> pool) {
this.pool = pool;
}
/**
* @param pool
* @param size 池大小
*/
public Producer(List<Product> pool, int size) {
this.pool = pool;
this.size = size;
}
/**
* @param pool
* @param size 池大小
* @param stepSize 一次生產多少
*/
public Producer(List<Product> pool, int size, int stepSize) {
this.pool = pool;
this.size = size;
this.stepSize = stepSize;
}
public void run() {
// TODO 生產者線程
//int pi = 0;
while(isRun) {//&& pi<10
//pi++;
synchronized (pool) { //同步產品池
if(pool.size() >= size) {
try {
System.out.println(name+" 等待!");
pool.wait(); //同步什么就等待什么,否則拋出java.lang.IllegalMonitorStateException
} catch (InterruptedException e) {
isRun = false;
System.out.println(name+" thread interrupt!");
}
} else {
for(int i=0; i<stepSize; i++) { //一次生產stepSize個產品
pool.add(product()); //生產產品
}
System.out.println("產品池中有: "+pool.size());
pool.notifyAll(); //通知等待的線程(主要用來通知消費者, 但生產者線程也會通知到)
}
}
try {
System.out.println(name+" 休息1秒!");
Thread.sleep(1000); //調試用
} catch (InterruptedException e) {
System.out.println(name+" sleep 1s thread interrupt");
}
}
System.out.println(name+" end! pool size: "+pool.size());
}
private static int P_ID = 0;
/**
* 生產產品
* @return 產品
*/
private Product product() {
String name = "product_"+(++P_ID);
System.out.println(this.name+" 生產了: "+name);
return new Production(name);
}
}
2.消費者:
package net.blogjava.chenlb.multithreaded;
import java.util.List;
/**
* @author chenlb
*
* 消費者
*/
public class Consumer implements Runnable {
private static int C_ID = 0; //消費者ID
private List<Product> pool = null;
private String name = "Consumer_"+(++C_ID);
private boolean isRun = true;
public Consumer(List<Product> pool) {
this.pool = pool;
}
public void run() {
// TODO 消費者線程
//int pi = 0;
while(isRun) {//&& pi<10
//pi++;
synchronized (pool) {
if(pool.size() < 1) {
try {
System.out.println(name+" 等待!");
pool.notifyAll(); //通知線程(主要是生產者,但也會通知到生產者線程)
pool.wait();
} catch (InterruptedException e) {
isRun = false;
System.out.println(name+" thread interrupt!");
}
} else {
Product p = pool.remove(0); //消費
printProduct(p);
}
}
try {
Thread.sleep(1000); //調試用
} catch (InterruptedException e) {
System.out.println(name+" sleep 1s thread interrupt");
}
}
System.out.println(name+" end! pool size: "+pool.size());
}
private void printProduct(Product p) {
System.out.println(name+" 消費了: "+p.getName());
}
}
import java.util.List;
/**
* @author chenlb
*
* 消費者
*/
public class Consumer implements Runnable {
private static int C_ID = 0; //消費者ID
private List<Product> pool = null;
private String name = "Consumer_"+(++C_ID);
private boolean isRun = true;
public Consumer(List<Product> pool) {
this.pool = pool;
}
public void run() {
// TODO 消費者線程
//int pi = 0;
while(isRun) {//&& pi<10
//pi++;
synchronized (pool) {
if(pool.size() < 1) {
try {
System.out.println(name+" 等待!");
pool.notifyAll(); //通知線程(主要是生產者,但也會通知到生產者線程)
pool.wait();
} catch (InterruptedException e) {
isRun = false;
System.out.println(name+" thread interrupt!");
}
} else {
Product p = pool.remove(0); //消費
printProduct(p);
}
}
try {
Thread.sleep(1000); //調試用
} catch (InterruptedException e) {
System.out.println(name+" sleep 1s thread interrupt");
}
}
System.out.println(name+" end! pool size: "+pool.size());
}
private void printProduct(Product p) {
System.out.println(name+" 消費了: "+p.getName());
}
}
3.Demo
package net.blogjava.chenlb.multithreaded;
import java.util.LinkedList;
import java.util.List;
/**
* @author chenlb
*
*/
public class Sale {
public static void main(String[] args) {
//鏈表產品池
List<Product> pool = new LinkedList<Product>();
//兩個生產者
Producer p1 = new Producer(pool);
Producer p2 = new Producer(pool);
Thread tp1 = new Thread(p1);
Thread tp2 = new Thread(p2);
tp1.start();
tp2.start();
//兩個消費者
Consumer c1 = new Consumer(pool);
Consumer c2 = new Consumer(pool);
Thread tc1 = new Thread(c1);
Thread tc2 = new Thread(c2);
tc1.start();
tc2.start();
}
}
import java.util.LinkedList;
import java.util.List;
/**
* @author chenlb
*
*/
public class Sale {
public static void main(String[] args) {
//鏈表產品池
List<Product> pool = new LinkedList<Product>();
//兩個生產者
Producer p1 = new Producer(pool);
Producer p2 = new Producer(pool);
Thread tp1 = new Thread(p1);
Thread tp2 = new Thread(p2);
tp1.start();
tp2.start();
//兩個消費者
Consumer c1 = new Consumer(pool);
Consumer c2 = new Consumer(pool);
Thread tc1 = new Thread(c1);
Thread tc2 = new Thread(c2);
tc1.start();
tc2.start();
}
}
注意:等待時候要用pool.wait()因為同步的是pool。否則會拋出java.lang.IllegalMonitorStateException
^_^
代碼下載