13.4 实例分析
本节将分析线程的一些比较实用的实例,通过这些实例和流程图,希望读者能够掌握线程的精髓。
13.4.1 生产者与消费者的模拟程序设计及分析
下面将使用生产者和消费者的模拟程序来编写代码,其条件是:
1个汉堡包店,有1个厨师和1个营业员,厨师负责做汉堡,营业员负责卖汉堡,当然还有1个存放汉堡的箱子。厨师不停地做汉堡,做好了就放在箱子里面,每次客人来的时候,营业员会从箱子里面取出1个汉堡卖掉。假设前提是客人每隔1秒来1个,也就是说营业员1秒卖1个汉堡,而厨师3秒做1个汉堡。
【实例13.15】目前总共只能做10个汉堡,箱子中已经有了5个汉堡,请编写一个程序代码来显示这个买卖的关系。
下面先看看程序的流程,如图13.2所示。
为了更好地掌握这个程序代码编制,下面将分步骤讲述这个代码。
图 13.2 生产者和消费者线程模拟程序
(1)设计汉堡包盒子类,将其作为监视点,代码如下所示。
01 ///创建一个汉堡包盒子的类
02 ///totalmaterial是指所有的能做汉堡包的材料
03 ///box是一个监视器对象
04 ///sales是指销售了多少个汉堡包
05 ///production是指总共有多少个汉堡包
06 class ham //把装汉堡包的盒子作为监视器类
07 {
08 static Object box=new Object();
09 static int totalmaterial=10;
10 static int sales=0;
11 static int production=5;
12 }
(2)设计厨师类,代码如下所示。
13 ///这是一个厨师的线程类
14 ///make方法使用了一个同步块,在这个函数里会不断地生产汉堡包
15 ///run方法就是线程需要运行的内容
16 ///使用循环语句来保证在汉堡包材料用完之前,不断地生产汉堡包
17 ///使用判断语句判断只要有汉堡包,厨师就通知营业员可以卖了
18 class hmaker extends Thread //厨师线程类
19 {
20 public void make()
21 {
22 synchronized(ham.box)
23 {
24 (ham.production)++;
25 try
26 {
27 ham.box.notify();
28 }
29 catch(Exception e){}
30 }
31 }
32 public void run()
33 {
34 while(ham.production<ham.totalmaterial)
35 {
36 if(ham.production>0)
37 {
38 System.out.println("厨师"+getName()+":"+"汉堡来了(总共
39 "+(ham.production-ham.sales)+"个)");
40 }
41 try
42 {
43 sleep(3000);
44 }
45 catch(Exception e){}
46 make();
47 }
48 }
49 }
(3)看看主运行程序的设计代码,如下所示。
50 ///这是一个营业员的线程类
51 ///sell函数是营业员卖汉堡包的方法
52 ///run方法就是线程需要运行的内容
53 ///使用条件判断语句来判断汉堡包盒子里面是否还有汉堡包
54 ///在run方法内使用循环语句来使得营业员在盒子里有汉堡包的情况下不断地卖
55 class hassistant extends Thread
56 {
57 public void sell()
58 {
59 if(ham.production==0)
60 {
61 System.out.println("营业员:顾客朋友们,请稍微等一下,汉堡没了!");
62 }
63 try
64 {
65 ham.box.wait();
66 }
67 catch(Exception e){}
68 ham.sales++;
69 System.out.println("营业员:顾客好,汉堡上来了,(总共卖了"+ham.sales+"个)");
70 }
71 public void run()
72 {
73 while(ham.sales<ham.production)
74 {
75 try
76 {
77 sleep(1000);
78 }
79 catch(Exception e){}
80 sell();
81 }
82 }
83 }
84 public class thread13
85 {
86 public static void main(String[]args)
87 {
88 hmaker maker=new hmaker();
89 hassistant assistant=new hassistant();
90 maker.setName("甲");
91 maker.start();
92 assistant.start();
93 }
94 }
【代码说明】首先根据同步的原理,第22行将存放汉堡的箱子作为监控点,为什么使用它作监控点呢?因为无论厨师还是营业员,都操作这个共同对象。第18~83行建立一个厨师类和一个营业员类。
厨师类能做到汉堡的产品数量,应该小于总材料的数量。在这个前提条件下,如果产品不等于零,就让厨师告诉一声:汉堡上来了,总共有多少个。接下来开始3秒做1个汉堡,做好了后,再通知一声:汉堡上来了,总共几个。另外,只要箱子里的汉堡不等于零,就通知营业员可以卖了。而营业员类,主要是销售汉堡,每1秒卖1个,如果箱子里面的汉堡等于零,就通知顾客:汉堡没了,需要等待。经过这些分析,重新阅读上面的程序,了解每个类的原理。
【运行效果】
厨师甲:汉堡来了(总共5个)
营业员:顾客好,汉堡上来了,(总共卖了1个)
营业员:顾客好,汉堡上来了,(总共卖了2个)
厨师甲:汉堡来了(总共4个)
营业员:顾客好,汉堡上来了,(总共卖了3个)
营业员:顾客好,汉堡上来了,(总共卖了4个)
营业员:顾客好,汉堡上来了,(总共卖了5个)
厨师甲:汉堡来了(总共2个)
营业员:顾客好,汉堡上来了,(总共卖了6个)
营业员:顾客好,汉堡上来了,(总共卖了7个)
厨师甲:汉堡来了(总共1个)
厨师甲:汉堡来了(总共2个)