我自己写了个生产者-消费者的多线程线程同步的代码,但是执行出来有一点点小问题,求帮忙找找原因。

那_年 2016-11-13 07:53:54
简单描述下:2个生产者,2个消费者,最多生产30个产品。线程同步。
出现了先消费最后生产的那个产品的情况。

下面直接上代码和结果。求帮忙分析下原因

import java.util.concurrent.locks.*;

public class ProducerConsumerDemo {
public static void main(String[] args) {

Store store = new Store();

Producer pro = new Producer(store);
Consumer con = new Consumer(store);

Thread t0 = new Thread(pro);
Thread t1 = new Thread(pro);
Thread t2 = new Thread(con);
Thread t3 = new Thread(con);

t0.start();
t1.start();
t2.start();
t3.start();

}
}

class Res {// 产品
private int num;

public Res(int num) {
this.num = num;
}

public int getNum() {
return num;
}

}

class Store {// 可以看做商店
private Res[] r = new Res[30];// 生产的最大容量

private Lock lock = new ReentrantLock();
Condition producer_con = lock.newCondition();
Condition consumer_con = lock.newCondition();

int producer_index;// 生产时数组指针
int consumer_index;// 消费时数组指针
int count;// 库存
int num;// 产品编号

public void produce() {// 生产--可以看做进货
lock.lock();
try{
while (count == r.length)
try{producer_con.await();}catch(Exception e){}
r[producer_index] = new Res(num);
System.out.println(Thread.currentThread().getName() + "生产了一个产品,产品编号为:" + r[producer_index].getNum());
try{Thread.sleep(50);}catch(Exception e){}//延迟
count++;// 库存加1
num++;// 编号加1
producer_index++;// 数组指针+1
if (producer_index == r.length - 1)// 数组最后一个元素位,重置指针为0
producer_index = 0;
consumer_con.signal();// 唤醒一次消费者。
} finally {
lock.unlock();
}
}

public void consume() {// 消费--可以看做卖货
lock.lock();
try {
while (count == 0)
try{consumer_con.await();}catch(Exception e){}
System.out.println(Thread.currentThread().getName() + "购买了一个产品,产品编号为:" + r[consumer_index].getNum());
try{Thread.sleep(50);}catch(Exception e){}//延迟
count--;// 库存减1
consumer_index++;// 数组指针+1
if (consumer_index == r.length - 1)// 数组最后一个元素位,重置指针为0
consumer_index = 0;
producer_con.signal();// 唤醒一次消费者。
} finally {
lock.unlock();
}
}
}

class Producer implements Runnable {// 生产者
private Store p;

public Producer(Store p) {
this.p = p;
}

public void run() {
while (true) {
p.produce();
}
}
}

class Consumer implements Runnable {// 消费者
private Store p;

public Consumer(Store p) {
this.p = p;
}

public void run() {
while (true) {
p.consume();
}
}
}



结果显示:

Thread-1生产了一个产品,产品编号为:0
Thread-1生产了一个产品,产品编号为:1
Thread-1生产了一个产品,产品编号为:2
Thread-1生产了一个产品,产品编号为:3
Thread-1生产了一个产品,产品编号为:4
Thread-1生产了一个产品,产品编号为:5
Thread-1生产了一个产品,产品编号为:6
Thread-1生产了一个产品,产品编号为:7
Thread-1生产了一个产品,产品编号为:8
Thread-1生产了一个产品,产品编号为:9
Thread-1生产了一个产品,产品编号为:10
Thread-1生产了一个产品,产品编号为:11
Thread-1生产了一个产品,产品编号为:12
Thread-1生产了一个产品,产品编号为:13
Thread-2购买了一个产品,产品编号为:0
Thread-2购买了一个产品,产品编号为:1
Thread-2购买了一个产品,产品编号为:2
Thread-2购买了一个产品,产品编号为:3
Thread-2购买了一个产品,产品编号为:4
Thread-2购买了一个产品,产品编号为:5
Thread-2购买了一个产品,产品编号为:6
Thread-2购买了一个产品,产品编号为:7
Thread-2购买了一个产品,产品编号为:8
Thread-2购买了一个产品,产品编号为:9
Thread-2购买了一个产品,产品编号为:10
Thread-2购买了一个产品,产品编号为:11
Thread-2购买了一个产品,产品编号为:12
Thread-2购买了一个产品,产品编号为:13
Thread-0生产了一个产品,产品编号为:14
Thread-0生产了一个产品,产品编号为:15
Thread-0生产了一个产品,产品编号为:16
Thread-0生产了一个产品,产品编号为:17
Thread-0生产了一个产品,产品编号为:18
Thread-0生产了一个产品,产品编号为:19
Thread-0生产了一个产品,产品编号为:20
Thread-0生产了一个产品,产品编号为:21
Thread-0生产了一个产品,产品编号为:22
Thread-0生产了一个产品,产品编号为:23
Thread-0生产了一个产品,产品编号为:24
Thread-0生产了一个产品,产品编号为:25
Thread-0生产了一个产品,产品编号为:26
Thread-0生产了一个产品,产品编号为:27
Thread-0生产了一个产品,产品编号为:28
Thread-0生产了一个产品,产品编号为:29
Thread-0生产了一个产品,产品编号为:30
Thread-0生产了一个产品,产品编号为:31
Thread-0生产了一个产品,产品编号为:32
Thread-0生产了一个产品,产品编号为:33
Thread-1生产了一个产品,产品编号为:34
Thread-1生产了一个产品,产品编号为:35
Thread-1生产了一个产品,产品编号为:36
Thread-1生产了一个产品,产品编号为:37
Thread-1生产了一个产品,产品编号为:38
Thread-1生产了一个产品,产品编号为:39
Thread-1生产了一个产品,产品编号为:40
Thread-1生产了一个产品,产品编号为:41
Thread-1生产了一个产品,产品编号为:42
Thread-1生产了一个产品,产品编号为:43
Thread-2购买了一个产品,产品编号为:43

Thread-2购买了一个产品,产品编号为:15
Thread-2购买了一个产品,产品编号为:16
Thread-2购买了一个产品,产品编号为:17
Thread-2购买了一个产品,产品编号为:18
Thread-2购买了一个产品,产品编号为:19
Thread-2购买了一个产品,产品编号为:20
Thread-2购买了一个产品,产品编号为:21
Thread-2购买了一个产品,产品编号为:22
Thread-2购买了一个产品,产品编号为:23
Thread-2购买了一个产品,产品编号为:24
Thread-2购买了一个产品,产品编号为:25
Thread-2购买了一个产品,产品编号为:26
Thread-2购买了一个产品,产品编号为:27
Thread-2购买了一个产品,产品编号为:28
Thread-2购买了一个产品,产品编号为:29
Thread-2购买了一个产品,产品编号为:30
Thread-2购买了一个产品,产品编号为:31


求帮忙分析下,结果里面,红色部分是怎么出现的。代码怎么改。
...全文
248 8 打赏 收藏 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
那_年 2016-11-15
  • 打赏
  • 举报
回复
引用 4 楼 lonrence 的回复:
if (producer_index == r.length - 1)// 数组最后一个元素位,重置指针为0 producer_index = 0; 这段是有问题的 改为if (producer_index == r.length)// 数组最后一个元素位,重置指针为0 producer_index = 0;
找到问题所在了,我的程序是先指针++再判断指针是否满,所以最后输出r[producer_index],producer_index是29,加一后是30,下次producer_index应该定位在0,而中间的判断应该是r.length不是r.length-1。 修改之后测试结果没问题了。
/*
Thread-0生产了一个产品,产品编号为:0
Thread-0生产了一个产品,产品编号为:1
Thread-0生产了一个产品,产品编号为:2
Thread-0生产了一个产品,产品编号为:3
Thread-0生产了一个产品,产品编号为:4
Thread-0生产了一个产品,产品编号为:5
Thread-0生产了一个产品,产品编号为:6
Thread-0生产了一个产品,产品编号为:7
Thread-0生产了一个产品,产品编号为:8
Thread-0生产了一个产品,产品编号为:9
Thread-0生产了一个产品,产品编号为:10
Thread-0生产了一个产品,产品编号为:11
Thread-0生产了一个产品,产品编号为:12
Thread-0生产了一个产品,产品编号为:13
Thread-0生产了一个产品,产品编号为:14
Thread-0生产了一个产品,产品编号为:15
Thread-0生产了一个产品,产品编号为:16
Thread-0生产了一个产品,产品编号为:17
Thread-0生产了一个产品,产品编号为:18
Thread-0生产了一个产品,产品编号为:19
Thread-0生产了一个产品,产品编号为:20
Thread-1生产了一个产品,产品编号为:21
Thread-1生产了一个产品,产品编号为:22
Thread-1生产了一个产品,产品编号为:23
Thread-1生产了一个产品,产品编号为:24
Thread-1生产了一个产品,产品编号为:25
Thread-1生产了一个产品,产品编号为:26
Thread-1生产了一个产品,产品编号为:27
Thread-1生产了一个产品,产品编号为:28
Thread-1生产了一个产品,产品编号为:29
Thread-2购买了一个产品,产品编号为:0
Thread-2购买了一个产品,产品编号为:1
Thread-2购买了一个产品,产品编号为:2
Thread-2购买了一个产品,产品编号为:3
Thread-2购买了一个产品,产品编号为:4
Thread-2购买了一个产品,产品编号为:5
Thread-2购买了一个产品,产品编号为:6
Thread-3购买了一个产品,产品编号为:7
Thread-3购买了一个产品,产品编号为:8
Thread-3购买了一个产品,产品编号为:9
Thread-3购买了一个产品,产品编号为:10
Thread-3购买了一个产品,产品编号为:11
Thread-3购买了一个产品,产品编号为:12
Thread-3购买了一个产品,产品编号为:13
Thread-3购买了一个产品,产品编号为:14
Thread-3购买了一个产品,产品编号为:15
Thread-3购买了一个产品,产品编号为:16
Thread-3购买了一个产品,产品编号为:17
Thread-3购买了一个产品,产品编号为:18
Thread-3购买了一个产品,产品编号为:19
Thread-3购买了一个产品,产品编号为:20
Thread-3购买了一个产品,产品编号为:21
Thread-3购买了一个产品,产品编号为:22
Thread-3购买了一个产品,产品编号为:23
Thread-3购买了一个产品,产品编号为:24
Thread-3购买了一个产品,产品编号为:25
Thread-3购买了一个产品,产品编号为:26
Thread-3购买了一个产品,产品编号为:27
Thread-3购买了一个产品,产品编号为:28
Thread-3购买了一个产品,产品编号为:29
Thread-0生产了一个产品,产品编号为:30
Thread-0生产了一个产品,产品编号为:31
Thread-0生产了一个产品,产品编号为:32
Thread-0生产了一个产品,产品编号为:33
Thread-0生产了一个产品,产品编号为:34
Thread-0生产了一个产品,产品编号为:35
Thread-0生产了一个产品,产品编号为:36
Thread-0生产了一个产品,产品编号为:37
Thread-0生产了一个产品,产品编号为:38
Thread-0生产了一个产品,产品编号为:39
Thread-1生产了一个产品,产品编号为:40
Thread-1生产了一个产品,产品编号为:41
Thread-1生产了一个产品,产品编号为:42
Thread-1生产了一个产品,产品编号为:43
Thread-2购买了一个产品,产品编号为:30
Thread-2购买了一个产品,产品编号为:31
Thread-2购买了一个产品,产品编号为:32
Thread-2购买了一个产品,产品编号为:33
Thread-3购买了一个产品,产品编号为:34
Thread-3购买了一个产品,产品编号为:35
Thread-3购买了一个产品,产品编号为:36
Thread-3购买了一个产品,产品编号为:37
Thread-3购买了一个产品,产品编号为:38
Thread-3购买了一个产品,产品编号为:39
Thread-3购买了一个产品,产品编号为:40
Thread-3购买了一个产品,产品编号为:41
Thread-3购买了一个产品,产品编号为:42
Thread-3购买了一个产品,产品编号为:43
Thread-0生产了一个产品,产品编号为:44
Thread-0生产了一个产品,产品编号为:45
Thread-1生产了一个产品,产品编号为:46
Thread-1生产了一个产品,产品编号为:47
Thread-1生产了一个产品,产品编号为:48
Thread-1生产了一个产品,产品编号为:49
Thread-1生产了一个产品,产品编号为:50
Thread-2购买了一个产品,产品编号为:44
Thread-2购买了一个产品,产品编号为:45
Thread-2购买了一个产品,产品编号为:46
Thread-2购买了一个产品,产品编号为:47
Thread-2购买了一个产品,产品编号为:48
Thread-2购买了一个产品,产品编号为:49
Thread-2购买了一个产品,产品编号为:50
Thread-0生产了一个产品,产品编号为:51
Thread-0生产了一个产品,产品编号为:52
Thread-0生产了一个产品,产品编号为:53
Thread-0生产了一个产品,产品编号为:54
Thread-0生产了一个产品,产品编号为:55
Thread-1生产了一个产品,产品编号为:56
Thread-1生产了一个产品,产品编号为:57
Thread-1生产了一个产品,产品编号为:58
Thread-1生产了一个产品,产品编号为:59*/
那_年 2016-11-15
  • 打赏
  • 举报
回复
引用 3 楼 达人游戏男孩的回复:
都没同步模块,这个写来有莫用?就用MQ吧
同步模块用锁代替了的
再不斩 2016-11-14
  • 打赏
  • 举报
回复
引用 5 楼 zaibuzhankkk 的回复:
因为在生产的时候,你的库存count也一直在增加。从打印来看,你是生产了43之后,消费线程占用资源,然后取出res对象,此时,count已经加到42了,所以取出来的是r[42],也就是name=43的res
不好意思,错了,不是count+到42了,应该是29,已经满了。
再不斩 2016-11-14
  • 打赏
  • 举报
回复
因为在生产的时候,你的库存count也一直在增加。从打印来看,你是生产了43之后,消费线程占用资源,然后取出res对象,此时,count已经加到42了,所以取出来的是r[42],也就是name=43的res
  • 打赏
  • 举报
回复
1、你的数组下标和num没有联系,生产一个num就增加 2、if (producer_index == r.length - 1)// 数组最后一个元素位,重置指针为0 producer_index = 0; 这段是有问题的 改为if (producer_index == r.length)// 数组最后一个元素位,重置指针为0 producer_index = 0;
达人游戏男孩 2016-11-14
  • 打赏
  • 举报
回复
都没同步模块,这个写来有莫用?就用MQ吧
那_年 2016-11-13
  • 打赏
  • 举报
回复
有的,我写的程序,理论上生产和消费都是指针从低到高循环的。 就是生产角标0-29-0-29,而它们的编号和它们的角标对应,但是循环到0,编号继续增大。消费也一样。、 所以理论上,生产和消费都是按编号从低到高显示的。 这个消费出现了先消费“库存”最近一个,然后消费前面的产品的情况。
捏造的信仰 2016-11-13
  • 打赏
  • 举报
回复
红色部分有问题吗?

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧