Java消费者远多于生产者时候,产生数组越界问题?
高洛峰
高洛峰 2016-10-24 14:11:58
0
1
557

问题描述

当消费者远多于生产者的时候,使用ReentrantLock会出现数组越界

使用Lock实现的

package xyz.hans.learning_java.pro_cu.lock; import xyz.hans.learning_java.pro_cu.common.IResource; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; /** * Created by Hans on 16/10/22. */ public class Resource implements IResource { private List mRes; private static final int MAX = 20; private static final Lock mLock = new ReentrantLock(true); private static final Condition mEmptyCondition = mLock.newCondition(); private static final Condition mFullCondition = mLock.newCondition(); public Resource() { mRes = new LinkedList<>(); } public String getRes() { mLock.lock(); if (mRes.size() <= 0) { //空仓的事后 则获取锁并且等待 try { System.out.println("空仓"); mEmptyCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("获取资源:" + mRes.get(0)); String res = mRes.remove(0); mFullCondition.signalAll(); mLock.unlock(); return res; } public void addRes(String res) { mLock.lock(); if (mRes.size() >= MAX) { try { System.out.println("爆仓"); mFullCondition.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("添加资源:" + res); mRes.add(res); mEmptyCondition.signalAll(); mLock.unlock(); } }

测试代码

Resource res = new Resource(); for (int i = 1; i < 3; i++) { new Productor("生产者:" + i, res).start(); } for (int i = 1; i < 200; i++) { new Customer("消费者:" + i, res).start(); }

2个生产者线程 199个消费者线程

Console面板日志

生产者:1生产了0号资源 生产者:2生产了0号资源 添加资源:生产者:1的0号资源 生产者:1生产了1号资源 添加资源:生产者:2的0号资源 生产者:2生产了1号资源 添加资源:生产者:1的1号资源 生产者:1生产了2号资源 添加资源:生产者:2的1号资源 生产者:2生产了2号资源 添加资源:生产者:1的2号资源 生产者:1生产了3号资源 添加资源:生产者:2的2号资源 添加资源:生产者:1的3号资源 生产者:2生产了3号资源 生产者:1生产了4号资源 添加资源:生产者:2的3号资源 生产者:2生产了4号资源 添加资源:生产者:1的4号资源 生产者:1生产了5号资源 添加资源:生产者:2的4号资源 生产者:2生产了5号资源 添加资源:生产者:1的5号资源 生产者:1生产了6号资源 添加资源:生产者:2的5号资源 生产者:2生产了6号资源 添加资源:生产者:1的6号资源 生产者:1生产了7号资源 添加资源:生产者:2的6号资源 生产者:2生产了7号资源 添加资源:生产者:1的7号资源 生产者:1生产了8号资源 添加资源:生产者:2的7号资源 生产者:2生产了8号资源 添加资源:生产者:1的8号资源 生产者:1生产了9号资源 添加资源:生产者:2的8号资源 生产者:2生产了9号资源 获取资源:生产者:1的0号资源 消费者:1消费者消耗资源:生产者:1的0号资源 添加资源:生产者:1的9号资源 生产者:1生产了10号资源 添加资源:生产者:2的9号资源 生产者:2生产了10号资源 获取资源:生产者:2的0号资源 消费者:2消费者消耗资源:生产者:2的0号资源 添加资源:生产者:1的10号资源 生产者:1生产了11号资源 获取资源:生产者:1的1号资源 消费者:3消费者消耗资源:生产者:1的1号资源 添加资源:生产者:2的10号资源 生产者:2生产了11号资源 获取资源:生产者:2的1号资源 消费者:4消费者消耗资源:生产者:2的1号资源 添加资源:生产者:1的11号资源 生产者:1生产了12号资源 添加资源:生产者:2的11号资源 生产者:2生产了12号资源 获取资源:生产者:1的2号资源 消费者:5消费者消耗资源:生产者:1的2号资源 获取资源:生产者:2的2号资源 消费者:6消费者消耗资源:生产者:2的2号资源 添加资源:生产者:1的12号资源 生产者:1生产了13号资源 添加资源:生产者:2的12号资源 生产者:2生产了13号资源 获取资源:生产者:1的3号资源 消费者:7消费者消耗资源:生产者:1的3号资源 获取资源:生产者:2的3号资源 消费者:8消费者消耗资源:生产者:2的3号资源 添加资源:生产者:1的13号资源 生产者:1生产了14号资源 添加资源:生产者:2的13号资源 生产者:2生产了14号资源 获取资源:生产者:1的4号资源 消费者:9消费者消耗资源:生产者:1的4号资源 获取资源:生产者:2的4号资源 消费者:10消费者消耗资源:生产者:2的4号资源 添加资源:生产者:1的14号资源 生产者:1生产了15号资源 获取资源:生产者:1的5号资源 消费者:11消费者消耗资源:生产者:1的5号资源 添加资源:生产者:2的14号资源 生产者:2生产了15号资源 获取资源:生产者:2的5号资源 消费者:12消费者消耗资源:生产者:2的5号资源 获取资源:生产者:1的6号资源 消费者:13消费者消耗资源:生产者:1的6号资源 添加资源:生产者:1的15号资源 生产者:1生产了16号资源 获取资源:生产者:2的6号资源 消费者:14消费者消耗资源:生产者:2的6号资源 添加资源:生产者:2的15号资源 生产者:2生产了16号资源 获取资源:生产者:1的7号资源 消费者:15消费者消耗资源:生产者:1的7号资源 添加资源:生产者:1的16号资源 生产者:1生产了17号资源 获取资源:生产者:2的7号资源 消费者:16消费者消耗资源:生产者:2的7号资源 添加资源:生产者:2的16号资源 生产者:2生产了17号资源 获取资源:生产者:1的8号资源 消费者:17消费者消耗资源:生产者:1的8号资源 添加资源:生产者:1的17号资源 生产者:1生产了18号资源 获取资源:生产者:2的8号资源 消费者:18消费者消耗资源:生产者:2的8号资源 添加资源:生产者:2的17号资源 生产者:2生产了18号资源 获取资源:生产者:1的9号资源 消费者:19消费者消耗资源:生产者:1的9号资源 添加资源:生产者:1的18号资源 生产者:1生产了19号资源 获取资源:生产者:2的9号资源 消费者:20消费者消耗资源:生产者:2的9号资源 获取资源:生产者:1的10号资源 消费者:21消费者消耗资源:生产者:1的10号资源 添加资源:生产者:2的18号资源 生产者:2生产了19号资源 获取资源:生产者:2的10号资源 消费者:22消费者消耗资源:生产者:2的10号资源 获取资源:生产者:1的11号资源 消费者:23消费者消耗资源:生产者:1的11号资源 添加资源:生产者:1的19号资源 生产者:1生产了20号资源 获取资源:生产者:2的11号资源 消费者:24消费者消耗资源:生产者:2的11号资源 获取资源:生产者:1的12号资源 消费者:25消费者消耗资源:生产者:1的12号资源 添加资源:生产者:2的19号资源 生产者:2生产了20号资源 获取资源:生产者:2的12号资源 消费者:26消费者消耗资源:生产者:2的12号资源 获取资源:生产者:1的13号资源 消费者:27消费者消耗资源:生产者:1的13号资源 获取资源:生产者:2的13号资源 消费者:28消费者消耗资源:生产者:2的13号资源 添加资源:生产者:1的20号资源 生产者:1生产了21号资源 获取资源:生产者:1的14号资源 消费者:29消费者消耗资源:生产者:1的14号资源 获取资源:生产者:2的14号资源 消费者:30消费者消耗资源:生产者:2的14号资源 添加资源:生产者:2的20号资源 生产者:2生产了21号资源 获取资源:生产者:1的15号资源 消费者:31消费者消耗资源:生产者:1的15号资源 获取资源:生产者:2的15号资源 消费者:32消费者消耗资源:生产者:2的15号资源 获取资源:生产者:1的16号资源 消费者:33消费者消耗资源:生产者:1的16号资源 获取资源:生产者:2的16号资源 消费者:34消费者消耗资源:生产者:2的16号资源 添加资源:生产者:1的21号资源 生产者:1生产了22号资源 获取资源:生产者:1的17号资源 消费者:35消费者消耗资源:生产者:1的17号资源 获取资源:生产者:2的17号资源 消费者:36消费者消耗资源:生产者:2的17号资源 获取资源:生产者:1的18号资源 消费者:37消费者消耗资源:生产者:1的18号资源 添加资源:生产者:2的21号资源 生产者:2生产了22号资源 获取资源:生产者:2的18号资源 消费者:38消费者消耗资源:生产者:2的18号资源 获取资源:生产者:1的19号资源 消费者:39消费者消耗资源:生产者:1的19号资源 获取资源:生产者:2的19号资源 消费者:40消费者消耗资源:生产者:2的19号资源 获取资源:生产者:1的20号资源 消费者:41消费者消耗资源:生产者:1的20号资源 获取资源:生产者:2的20号资源 消费者:42消费者消耗资源:生产者:2的20号资源 添加资源:生产者:1的22号资源 生产者:1生产了23号资源 获取资源:生产者:1的21号资源 消费者:43消费者消耗资源:生产者:1的21号资源 获取资源:生产者:2的21号资源 消费者:44消费者消耗资源:生产者:2的21号资源 获取资源:生产者:1的22号资源 消费者:45消费者消耗资源:生产者:1的22号资源 空仓 空仓 添加资源:生产者:2的22号资源 生产者:2生产了23号资源 获取资源:生产者:2的22号资源 消费者:48消费者消耗资源:生产者:2的22号资源 空仓 空仓 空仓 空仓 空仓 空仓 空仓 添加资源:生产者:1的23号资源 生产者:1生产了24号资源 获取资源:生产者:1的23号资源 消费者:56消费者消耗资源:生产者:1的23号资源 空仓 空仓 空仓 空仓 空仓 空仓 Exception in thread "消费者:46" java.lang.IndexOutOfBoundsException: Index: 0, Size: 0 at java.util.LinkedList.checkElementIndex(LinkedList.java:553) at java.util.LinkedList.get(LinkedList.java:474) at xyz.hans.learning_java.pro_cu.lock.Resource.getRes(Resource.java:37)

请求帮助

为何在锁的情况下还会产生这种问题?

如何完美解决呢?

谢谢您的回复


高洛峰
高洛峰

拥有18年软件开发和IT教学经验。曾任多家上市公司技术总监、架构师、项目经理、高级软件工程师等职务。 网络人气名人讲师,...

Antworte allen (1)
三叔

应该是这里的问题:

if (mRes.size()

如果这里有多个线程阻塞在mEmptyCondition.await();,当mEmptyCondition执行signalAll的时候,会唤醒所有正在阻塞的线程,第一个线程获得锁执行没问题,第二个在生成之前获得锁就会报出结果里的异常了。

可以把if改成while,或list的实现采用blocking实现。


    Neueste Downloads
    Mehr>
    Web-Effekte
    Quellcode der Website
    Website-Materialien
    Frontend-Vorlage
    Über uns Haftungsausschluss Sitemap
    Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!