问题描述:
生产者和消费者问题,我想大家肯定都很熟悉。就是有生产者在生产,生产出的产品(我们在这里用窝头来作比喻)放到一个篮子里,然后有消费者拿篮子里的窝头来吃。
问题分析:
1、条件分析,如果生产者生产了窝头,就应该叫消费者来吃;如果自己生产的窝头把篮子都装满了,就要先停下来,然后通知消费者去吃窝头;同理,消费者吃了窝头,应该叫生产者生产窝头,如果自己把篮子里的馒头都消费了,那么,就要先停下来,然后通知生产者生产窝头。
2、我们用面向对象的分析方法来分析这个问题:
其中的对象有:生产者(Producer)、消费者(Consumer)、篮子(SyncStack)、窝头(WoTou)
我写的代码如下:
[java]
复制 打印
1. public class ProducerConsumer
2. {
3. public static void main(String[] args)
4. {
5. SyncStack ss=new SyncStack();
6. new Thread(new Producer(ss)).start();
7. new Thread(new Consumer(ss)).start();
8. }
9. }
10.
11. class WoTou
12. {
13. int id;
14. WoTou(int id)
15. {
16. this.id=id;
17. }
18.
19. public String toString()
20. {
21. return "窝头"+id;
22. }
23. }
24.
25. //生产池
26. class SyncStack
27. {
28. int index=0; //标记现在有几个馒头
29. WoTou[] arrayWoTou=new WoTou[6];
30.
31. //生产者向生产池中放入窝头
32. public synchronized void push(WoTou wt)
33. {
34. //要用while不用能if 如果用if的话出现例外后,会继续向下执行,索引溢出
35. while(index>=6)
36. {
37. try
38. {
39. this.wait();
40. }
41. catch(InterruptedException e)
42. {
43. e.printStackTrace();
44. }
45. }
46.
47. notify();
48. arrayWoTou[index]=wt;
49. index++;
50. }
51.
52. //消费者从生活池中消费窝头
53. public synchronized WoTou pop()
54. {
55. while(index<=0)
56. {
57. try
58. {
59. this.wait();
60. }
61. catch(InterruptedException e)
62. {
63. e.printStackTrace();
64. }
65. }
66.
67. notify();
68. //先要index--因为index记录的是当前窝头的个数
69. index--;
70. return arrayWoTou[index];
71. }
72. }
73.
74. //生产者
75. class Producer implements Runnable
76. {
77. SyncStack ss=new SyncStack();
78. Producer(SyncStack ss)
79. {
80. this.ss=ss;
81. }
82. public void run()
83. {
84. for(int i=1;i<=10;i++)
85. {
86. WoTou wt=new WoTou(i);
87. ss.push(wt);
88. System.out.println("生产了:"+wt);
89. }
90. }
91. }
92.
93. //消费者
94. class Consumer implements Runnable
95. {
96. SyncStack ss=new SyncStack();
97. Consumer(SyncStack ss)
98. {
99. this.ss=ss;
100. }
101. public void run()
102. {
103. for(int i=1;i<=10;i++)
104. {
105. WoTou wt=null;
106. wt=ss.pop();
107. System.out.println("消费了"+wt);
108. }
109. }
110. }
public class ProducerConsumer
{
public static void main(String[] args)
{
SyncStack ss=new SyncStack();
new Thread(new Producer(ss)).start();
new Thread(new Consumer(ss)).start();
}
}
class WoTou
{
int id;
WoTou(int id)
{
this.id=id;
}
public String toString()
{
return "窝头"+id;
}
}
//生产池
class SyncStack
{
int index=0; //标记现在有几个馒头
WoTou[] arrayWoTou=new WoTou[6];
//生产者向生产池中放入窝头
public synchronized void push(WoTou wt)
{
//要用while不用能if 如果用if的话出现例外后,会继续向下执行,索引溢出
while(index>=6)
{
try
{
this.wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
notify();
arrayWoTou[index]=wt;
index++;
}
//消费者从生活池中消费窝头
public synchronized WoTou pop()
{
while(index<=0)
{
try
{
this.wait();
}
catch(InterruptedException e)
{
e.printStackTrace();
}
}
notify();
//先要index--因为index记录的是当前窝头的个数
index--;
return arrayWoTou[index];
}
}
//生产者
class Producer implements Runnable
{
SyncStack ss=new SyncStack();
Producer(SyncStack ss)
{
this.ss=ss;
}
public void run()
{
for(int i=1;i<=10;i++)
{
WoTou wt=new WoTou(i);
ss.push(wt);
System.out.println("生产了:"+wt);
}
}
}
//消费者
class Consumer implements Runnable
{
SyncStack ss=new SyncStack();
Consumer(SyncStack ss)
{
this.ss=ss;
}
public void run()
{
for(int i=1;i<=10;i++)
{
WoTou wt=null;
wt=ss.pop();
System.out.println("消费了"+wt);
}
}
}
1、一个时间点只有一个进程在这个对象上
2、如果是多个生产者或者消费者的话,生产和消费的数量应该一致,比如说如果再增加两个生产者,每个生产者都还是生产20个,可是只有一个消费者,总共消费20个,会出现满的情况;还有就是调用notifyAll(),在这个对象上的线程一哄而起,谁抢到算谁的。
QQ 744437114
疯狂软件官网:http://www.fkjava.org
疯狂java视频 android视频:http://www.fkjava.org/video.html |
|