13.4.2 多消费者的模拟程序设计及分析

【实例13.16】本节将接着上面的实例,再增加条件:增加一个营业员,即现在是两个营业员在销售汉堡,而一个厨师在做汉堡。


先来看看程序的流程,如图13.3所示。

13.4.2 多消费者的模拟程序设计及分析 - 图1

图 13.3 多消费者线程模拟程序

为了能够更加清晰地理解这个程序,下面将分步骤讲述。

(1)设计箱子类,代码如下所示。


01 ///创建一个汉堡包盒子的类

02 ///totalmaterial是指所有的能做汉堡包的材料

03 ///box是一个监视器对象

04 ///sale1,sale2是指销售了多少个汉堡包

05 ///production是指总共有多少个汉堡包

06 class ham

07 {

08 static Object box=new Object();

09 static int totalmaterial=10;

10 static int sales1=0;

11 static int sales2=0;

12 static int production=5;

13 }


(2)设计厨师类,代码如下所示。


14 ///这是一个厨师的线程类

15 ///make方法使用了一个同步块,在这个函数里会不断地生产汉堡包

16 ///run方法就是线程需要运行的内容

17 ///使用循环语句来保证在汉堡包材料用完之前,不断地生产汉堡包

18 ///使用判断语句判断只要有汉堡包,厨师就通知营业员可以卖了

19 class hmaker extends Thread

20 {

21 public void make()

22 {

23 synchronized(ham.box)

24 {

25 (ham.production)++;

26 System.out.println("厨师"+getName()+":"+"汉堡来了(总共

27 "+(ham.production-ham.sales1-ham.sales2)+"个)");

28 try

29 {

30 ham.box.notify();

31 }

32 catch(Exception e){}

33 }

34 }

35 public void run()

36 {

37 while(ham.production<ham.totalmaterial)

38 {

39 make();

40 try

41 {

42 sleep(3000);

43 }

44 catch(Exception e){}

45 }

46 }

47 }


(3)修改营业员类的设计,其代码如下所示。


48 ///这是一个营业员的线程类

49 ///sell1、sell2函数都是营业员卖汉堡包的方法

50 ///run方法就是线程需要运行的内容

51 ///使用条件判断语句来判断汉堡包盒子里面是否还有汉堡包

52 ///在run方法内使用循环语句来使得营业员在盒子里面有汉堡包的情况下不断地卖

53 class hassistant extends Thread

54 {

55 public void sell1()

56 {

57 if(ham.production==(ham.sales1+ham.sales2))

58 {

59 System.out.println("营业员"+getName()+":顾客朋友们,请稍微等一下,汉堡没了!");

60 61

ham.sales1=0;

62 ham.production=0;

63 try

64 {

65 ham.box.wait();

66 }

67 catch(Exception e){}

68 }

69 (ham.sales1)++;

70 System.out.println("营业员"+getName()+":顾客好,汉堡上来了,(总共卖了"

71 +ham.sales1+"个)");

72 }

73 public void sell2()

74 {

75 if(ham.production==(ham.sales1+ham.sales2))

76 {

77 System.out.println("营业员"+getName()+":顾客朋友们,请稍微等一下,汉堡没

78 了!");

79 ham.sales2=0;

80 ham.production=0;

81 try

82 {

83 ham.box.wait();

84 }

85 catch(Exception e){}

86 }

87 (ham.sales2)++;

88 System.out.println("营业员"+getName()+":顾客好,汉堡上来了,(总共卖了"

89 +ham.sales2+"个)");

90 }

91 public void run()

92 {

93 while((ham.sales1+ham.sales2)<ham.production)

94 {

95 sell1();

96 try

97 {

98 sleep(1000);

99 }

100 catch(Exception e){}

101 }

102 while((ham.sales1+ham.sales2)<ham.production)

103 {

104 try

105 {

106 sleep(1000);

107 }

108 catch(Exception e){}

109 sell2();

110 }

111 }

112 }


(4)线程类在主运行程序中运行,详细代码如下所示。


113 ///这是主运行类

114 ///maker对象是指厨师对象

115 ///assistant1是指第一个营业员对象

116 ///assistant2是指第二个营业员对象

117 ///set方法是通过设置名字不同而区分不同的营业员

118 ///start方法是线程的开始

119 public class thread14

120 {

121 public static void main(String[]args)

122 {

123 hmaker maker=new hmaker();

124 hassistant assistant1=new hassistant();

125 hassistant assistant2=new hassistant();

126 assistant1.setName("甲");

127 assistant2.setName("乙");

128 maker.setName("甲");

129 maker.start();

130 assistant1.start();

131 assistant2.start();

132 }

133 }


【代码说明】这个程序涉及两个营业员,其实多几个营业员倒是不难,只是要注意此时是两个人卖汉堡。那么厨师做出来的汉堡,就必须与两个营业员的销售总量进行比较,这一点也是整个程序比前一小节要多考虑的问题。

【运行效果】


厨师甲:汉堡来了(总共6个)

营业员甲:顾客好,汉堡上来了,(总共卖了1个)

营业员乙:顾客好,汉堡上来了,(总共卖了2个)

营业员甲:顾客好,汉堡上来了,(总共卖了3个)

营业员乙:顾客好,汉堡上来了,(总共卖了4个)

营业员甲:顾客好,汉堡上来了,(总共卖了5个)

营业员乙:顾客好,汉堡上来了,(总共卖了6个)

厨师甲:汉堡来了(总共1个)

营业员甲:顾客好,汉堡上来了,(总共卖了7个)

厨师甲:汉堡来了(总共1个)

厨师甲:汉堡来了(总共2个)

厨师甲:汉堡来了(总共3个)