import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;public class Producer {
private final Queue<String> productQueue = new LinkedBlockingQueue<String> ();
private final List<Consumer> consumers = new ArrayList<Consumer> ();
public void addConsumer(Consumer c) {
this.consumers.add(c);
}
public void notifyProductGenerated() {
for(Consumer c : this.consumers) {
c.notifyProductGenerated();
}
}
public static void main(String... args) {
Producer producer = new Producer();
final Consumer consumer = new Consumer(producer.productQueue);
producer.addConsumer(consumer);
new Thread(new Runnable() {
@Override
public void run() {
consumer.consume();
}
}).start();
for(int i = 0; i < 100; i++) {
try {
Thread.sleep(1000 * 1);
} catch(InterruptedException ex) {
ex.printStackTrace();
}
producer.productQueue.add("" + i);
System.out.println("" + i + " made.");
producer.notifyProductGenerated();
}
}
}class Consumer {
private Queue<String> productQueue;
public Consumer(Queue<String> productQueue) {
this.productQueue = productQueue;
}
public synchronized void notifyProductGenerated() {
notifyAll();
}
public synchronized void consume() {
String product = null;
while(true) {
product = productQueue.poll();
if(product == null) {
try {
wait();
continue;
} catch (InterruptedException ex) {
ex.printStackTrace();
return;
}
}
try {
Thread.sleep(1000 * 10);
} catch(InterruptedException ex) {
ex.printStackTrace();
return;
}
System.out.println("run out of product " + product);
}
}
}
以上代码是模拟生产者与消费者。当生产者生成出产品后,将通知消费者,消费都进而消费。
代码中设计成消费者每一秒生产一个产品,而消费者每10秒才能消费一个产品。
所以,我期待的输出应该像这样(输出一):
0 made.
1 made.
2 made.
3 made.
4 made.
5 made.
6 made.
7 made.
8 made.
9 made.
10 made.
run out of product 0
11 made.
12 made.
...然而输出的结果却是这样(输出二):
0 made.
1 made.
run out of product 0
run out of product 1
2 made.
3 made.
run out of product 2
run out of product 3
4 made.
...似乎是生产者在生产两个产品后,就在等待消费者消费,待消费者消费完成后再行生产。请各位大侠帮忙看看,如果要达到输出一的效果,代码中应该如何调整?谢谢!
解决方案 »
- 简单的Socket问题
- 讨论:Java到底有没有办法把thread绑定CPU或者虚拟绑定CPU运行?
- AffineTransform问题求救,在线等啊,谢谢了
- Deque 接口的大小可变数组的实现
- 软通动力编程题,解析之后排序
- 弹出式菜单没有弹出菜单
- 关于验证SQL语句的问题!!!!!!!!!!!!!!
- 关于jList。jdbList控件的应用(毕业设计急用),请教,谢谢!
- 请大家以自己实际的感觉讲述一下在Web开发中.net和java谁更有优势?进者有分!
- ~急~####高分请教,不知道在哪问了,怎么在oracle中编写存储进程存入BLOB类型数据,最好是要有源程序!!
- 有次笔试的题目,format方法的实现,没想出更好办法
- java多线程问题,以上生产者和消费者java程序为什么会出现死锁,如何修改,请大神赐教
再说已经有wait了,只要生产者生产够了10个产品,就通知消费者消费,同时等待
消费完了消费者再通知生产者继续生产
1 根据线程同步规则,concume()执行时时不释放其同步对象的锁旗标的,所以在其sleep(10000)时间里,main 线程因要执行notifyProductGenerated()这个方法,而在等待池里等待锁旗标,而什么也干不了。(无法生产)。
2 根据上面的分析,关键是在consume等待时,不占有锁旗标,所以对consume()进行修改如下:
public void consume()
{
String product = null;
int number=0; //计数器,到100时线程正常结束。
while(number<100)
{
try //把休眠等待放在同步块外。
{
Thread.sleep(100*10);
}
catch(InterruptedException ex)
{
ex.printStackTrace();
} synchronized(this) //与notifyProductGenerated()共用同一同步对象。
{
product = productQueue.poll();
if(product == null)
{
try
{
wait();
continue; //?
}
catch (InterruptedException ex)
{
ex.printStackTrace();
return;
}
}//end if(product == null)
System.out.println("run out of product " + product);
}//end synchronized block.
number++;
}//end while
}//end consume.
休眠的时间为了调试的快,改小了。 楼主再改回即可。
class Info
{
private String value=null;
private String key=null;
private boolean flag=false;
public synchronized void set(String value,String key)
{
if(flag)
{
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
this.setKey(key);
this.setValue(value);
flag=true;
super.notify();
}
public void setValue(String value)
{
this.value=value;
}
public void setKey(String key)
{
this.key=key;
}
public String getKey()
{
return this.key;
}
public String getValue()
{
return this.value;
}
public synchronized void get()
{
if(!flag)
{
try {
super.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println(this.getKey()+"-----------"+this.getValue());
flag=false;
super.notify();
}
}
class SetRun implements Runnable
{
private Info info=null;
public SetRun(Info info)
{
this.info=info;
}
public void run()
{
boolean flag=false;
for(int i=0;i<50;i++)
{
if(flag)
{
this.info.set("河南大学","henu.edu.cn");
flag=false;
}
else
{
this.info.set("百度","www.baidu.com");
flag=true;
}
}
}
}
class GetRun implements Runnable
{
private Info info=null;
public GetRun(Info info)
{
this.info=info;
}
public void run()
{
for(int i=0;i<50;i++)
{
this.info.get();
}
}
}
public class MyThread
{
public static void main(String[] args)
{
Info info=new Info();
new Thread(new SetRun(info)).start();
new Thread(new GetRun(info)).start();
}}