花了点时间写了生产者消费者的小程序,凑和凑和.......
假设cd店中有固定的两种cd。编写一个线程类为cd店进货,一个线程类为会员买cd。
要求:
进货线程只有1个,固定的每1000ms启动一次,但是如果临时缺货则购买线程发送消息10ms后启动一次,每次为两种cd各购买10个。
销售线程可以有2个或2个以上,启动的时间为500ms以内的随机数。购买数量为5以内的随机数。如果cd数量不足则随机选择等候或放弃。
程序运行1分钟后停止,最后列出销售和购买记录。
import java.util.Random;
import java.util.concurrent.Semaphore;
class Producer implements Runnable{
private long nowstarttime;
private long laststarttime;
private static int wake_sleep_time = 10; //被唤醒时需睡眠一段时间
public Producer()
{
laststarttime = System.currentTimeMillis();
}
public void run() //进货线程
{
while(true)
{
try{
nowstarttime = System.currentTimeMillis();
if((nowstarttime-laststarttime) < main.wait_time) //被唤醒时进货前先睡眠一段时间
{
System.out.println("producer called up by customer");
Thread.sleep(wake_sleep_time); //进货前先休眠
}
main.produce(); //进货
laststarttime = nowstarttime; //记录上次运行时间
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
class Customer extends Thread{ //销售线程
private static int id = 1;
private int customerid;
private static int time_start = 500; //购买线程启动时间最大值
public Customer()
{
customerid = id++;
this.setName("customer "+customerid); //消费者编号
}
public void run()
{
try {
while(true)
{
int sleep_time = main.randint(time_start); //随机睡眠时间
Thread.sleep(sleep_time);
boolean enough = main.buy(); //是否购买成功
if(!enough) //购买失败
{
if(sleep_time%2 == 0) //根据随机睡眠时间决定是否等待
{
System.out.println(Thread.currentThread().getName()+" give up"); //放弃
break;
}
else
{
System.out.println(Thread.currentThread().getName()+" wait"); //等待
}
}
else //购买成功
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
public class main {
/**
* @param args
*/
private static int customer_thread_count = 500; //销售线程数量
private static int cd_want = 5; //每次购买数量最大值
public static int wait_time = 1000; //每隔固定时间启动进货线程
private static Object wake_sign = new Object(); //唤醒线程同步信号
private static int cd1_instore = 0; //当前库存的CD1数量
private static int cd2_instore = 0; //当前库存的CD1数量
private static Semaphore mutex = new Semaphore(1); //互斥信号量
public static int randint(int number) //产生number以内的随机数
{
Random rnd = new Random();
return rnd.nextInt(number);
}
public static void produce()
{
try
{
mutex.acquire(); //进入临界区
cd1_instore += 10; //增加库存
cd2_instore += 10;
System.out.println("produce success!");
mutex.release(); //离开临界区
synchronized(wake_sign)
{
wake_sign.wait(wait_time); //每隔一段时间进货或等待销售线程唤醒
}
}catch(InterruptedException e)
{
e.printStackTrace();
}
}
public static boolean buy()
{
int cd1_want = randint(cd_want); //购买CD1数量
int cd2_want = randint(cd_want-cd1_want); //购买CD2数量
try
{
mutex.acquire(); //进入临界区
if((cd1_want <= cd1_instore) && (cd2_want <= cd2_instore)) //库存CD是否足够
{
cd1_instore -= cd1_want; //购买成功
cd2_instore -= cd2_want;
System.out.println(Thread.currentThread().getName()+
" get:"+" CD1 "+cd1_want+" CD2 "+cd2_want+" success");
mutex.release(); //离开临界区
return true;
}
else
{
System.out.println(Thread.currentThread().getName()+
" get:"+" CD1 "+cd1_want+" CD2 "+cd2_want+" fail");
mutex.release(); //离开临界区
synchronized(wake_sign)
{
wake_sign.notifyAll(); //唤醒进货线程
}
return false; //购买失败
}
} catch (InterruptedException e) {
e.printStackTrace();
return false;
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("start process");
long runtime = 60000; //程序运行时间
long starttime = System.currentTimeMillis();
new Thread(new Producer()).start(); //启动进货线程
for(int i = 0; i < customer_thread_count; i++)
new Customer().start(); //销售线程
do
{
long endtime = System.currentTimeMillis();
if(endtime-starttime >= runtime) //运行1分钟停止
System.exit(0);
}while(true);
}
}
程序写下来,才发现线程等待和唤醒线程wait和notifyAll的调用对象是Object,而不是线程Thread,关系还是有点乱,学艺不精啊.......