一个多线程小程序

今天看见一个多线程问题,心里痒痒,就做了做,然后就有了这么一个小程序。

问题在这里:[url]http://www.iteye.com/problems/46763[/url]

有三方:厂家,电脑城,顾客
厂家2个,一个生产主板,一个生产显卡。
顾客有2个,他们各自不断购买主板和显卡。
电脑城有一个,卖显卡和主板。

货品类,方便调试:

public class Product {
private String name;
private int serial;

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public int getSerial() {
return serial;
}

public void setSerial(int serial) {
this.serial = serial;
}
}


货品供需管理类,多线程调度的核心:
import java.util.ArrayDeque;

public class StockManager {
private final Object producerLock = new Object();
private final Object consumerLock = new Object();
private final int MAX_SIZE = 10;

private final ArrayDeque queue = new ArrayDeque();

public void stock(Product p) throws InterruptedException {
synchronized (producerLock) {
if (queue.size() >= MAX_SIZE) {
producerLock.wait();
}
}
synchronized (queue) {
queue.add(p);
}
synchronized (consumerLock) {
consumerLock.notify();
}
}

public synchronized Product purchase() throws InterruptedException {
synchronized (consumerLock) {
if (queue.size() <= 0) {
consumerLock.wait();
}
}
Product product = null;
synchronized (queue) {
product = queue.remove();
}
synchronized (producerLock) {
producerLock.notify();
}
return product;
}
}


厂商类,可以生产产品,另有一个run,用于实现具体的生产过程,以调节测试时的供求关系:
import java.util.logging.Logger;

public class Producer implements Runnable{
private static final Logger log = Logger.getLogger(Producer.class.getName());

private String productName = null;
private int serial = 0;
private StockManager stockManager;

public void setProductName(String productName) {
this.productName = productName;
}

public void setStockManager(StockManager stockManager) {
this.stockManager = stockManager;
}

public Product produce() {
final Product p = new Product();
p.setName(productName);
p.setSerial(++serial);
return p;
}

@Override
public void run() {
try {
for( int i = 0; i < 20; i++) {
deliver();
}
Thread.sleep(30 * 1000);
while (true) {
deliver();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}

private void deliver() throws InterruptedException {
final long s = System.currentTimeMillis();
final Product product = produce();
stockManager.stock(product);
final long time = System.currentTimeMillis() - s;
if (time > 10) {
log.info(product.getName() + ", No. " +
product.getSerial() + " took " +
time + " milli seconds to finish." );
}
}
}


客户类,比较简单,外加调试信息:
import java.util.logging.Logger;

public class Consumer implements Runnable {
private static final Logger log = Logger.getLogger(Consumer.class.getName());

private String name;
private StockManager[] stockManagers;

public void setName(String name) {
this.name = name;
}

public void setStockManagers(StockManager[] stockManagers) {
this.stockManagers = stockManagers;
}

@Override
public void run() {
for (int i = 0; i < 50; i++) {
final double v = Math.random() * stockManagers.length;
final int k = (int) Math.floor(v);
try {
final long s = System.currentTimeMillis();
final Product product = stockManagers[k].purchase();
final long time = System.currentTimeMillis() - s;
String l = "";
if (time > 10) {
l += "after " + time + " milli seconds of waiting, ";
}
l += (name + " bought product " + product.getName()
+ ", serial No. " + product.getSerial());
log.info(l);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}


程序入口,初始化上述各类,启动相应线程:
public class Mall {
public static void main(String[] args) {
final StockManager mb = new StockManager();
final Producer pmb = new Producer();
pmb.setProductName("Motherboard");
pmb.setStockManager(mb);

final StockManager vd = new StockManager();
final Producer pvd = new Producer();
pvd.setProductName("Video Card");
pvd.setStockManager(vd);

final StockManager[] stockManagers = new StockManager[2];
stockManagers[0] = mb;
stockManagers[1] = vd;

final Consumer c1 = new Consumer();
c1.setName("C1");
c1.setStockManagers(stockManagers);

final Consumer c2 = new Consumer();
c2.setName("C2");
c2.setStockManagers(stockManagers);

final Thread tc1 = new Thread(c1);
tc1.start();
final Thread tc2 = new Thread(c2);
tc2.start();

try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}

new Thread(pmb).start();
new Thread(pvd).start();

try {
tc1.join();
tc2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

// kill system after consumer done shopping
System.exit(0);
}
}


感觉StockManager还是有些问题,但是又说不清楚。

你可能感兴趣的:(一个多线程小程序)