BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #64232同步于 2020/8/14
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

【问题】Java生产者消费者多线程问题

lxx909546478
2020/8/14镜像同步11 回复
这段代码是模拟生产者消费者问题,请问这段代码有什么问题吗?为什么运行时总是一个线程连着生产或消费10个然后其他线程继续呢?如果想要实现线程交替生产消费,应该怎样编写呢? import java.util.ArrayList; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; public class ProducerAndConsumer { private static final Integer FULL = 10; private static ArrayList<Goods> cache=new ArrayList(); private static final int PRODUCER_NUM=4; private static final int CUSTOMER_NUM=3; public static void main(String[] args) { ProducerAndConsumer producerAndConsumer=new ProducerAndConsumer(); ExecutorService pool= Executors.newCachedThreadPool(); for (int i=0;i<PRODUCER_NUM;i++){ pool.execute(producerAndConsumer.new Producer(i+1)); } for (int i=0;i<CUSTOMER_NUM;i++){ pool.execute(producerAndConsumer.new Consumer(i+1)); } } static class Goods{ private static int id=0; Goods(){id++;} @Override public String toString() { return "Goods"+id; } } class Producer implements Runnable{ private final int id; Producer(int id){this.id=id;} @Override public void run() { while (true){ synchronized (cache){ while (cache.size()==FULL){ try { cache.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cache.add(new Goods()); System.out.println("Producer "+id+" put in cache. Cache size is "+cache.size()); cache.notifyAll(); } } } } class Consumer implements Runnable{ private final int id; Consumer(int id){this.id=id;} @Override public void run() { while (true){ synchronized (cache){ while (cache.size()==0){ try { cache.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } try { TimeUnit.MILLISECONDS.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } cache.remove(0); System.out.println("Consumer "+id+" fetch from cache. Cache size is "+cache.size()); cache.notifyAll(); } } } } }
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
lxx909546478机器人#1 · 2020/8/14
补充一下运行结果: Producer 1 put in cache. Cache size is 1 Producer 1 put in cache. Cache size is 2 Producer 1 put in cache. Cache size is 3 Producer 1 put in cache. Cache size is 4 Producer 1 put in cache. Cache size is 5 Producer 1 put in cache. Cache size is 6 Producer 1 put in cache. Cache size is 7 Producer 1 put in cache. Cache size is 8 Producer 1 put in cache. Cache size is 9 Producer 1 put in cache. Cache size is 10 Consumer 3 fetch from cache. Cache size is 9 Consumer 3 fetch from cache. Cache size is 8 Consumer 3 fetch from cache. Cache size is 7 Consumer 3 fetch from cache. Cache size is 6 Consumer 3 fetch from cache. Cache size is 5 Consumer 3 fetch from cache. Cache size is 4 Consumer 3 fetch from cache. Cache size is 3 Consumer 3 fetch from cache. Cache size is 2 Consumer 3 fetch from cache. Cache size is 1 Consumer 3 fetch from cache. Cache size is 0 Producer 4 put in cache. Cache size is 1 Producer 4 put in cache. Cache size is 2 Producer 4 put in cache. Cache size is 3 Producer 4 put in cache. Cache size is 4 Producer 4 put in cache. Cache size is 5 Producer 4 put in cache. Cache size is 6 Producer 4 put in cache. Cache size is 7 Producer 4 put in cache. Cache size is 8 Producer 4 put in cache. Cache size is 9 Producer 4 put in cache. Cache size is 10
xuanyu66机器人#2 · 2020/8/14
两个synchronized代码块后加一个thread.yield()。 或者sleep一下都行
xuanyu66机器人#3 · 2020/8/14
and,感觉用reetrantlock和condition搭配比较好,因为可读可写其实是两个状态,代码看起来也易读一些
xuanyu66机器人#4 · 2020/8/14
annd,这个代码还有一个问题就是读和取是互相阻塞的。但是其实这两者没啥并发关系
lxx909546478机器人#5 · 2020/8/14
对的,生产者消费者问题的缓冲区好像只有一个线程能同时进入,这好像是题目的条件? 【 在 xuanyu66 (angry_yang) 的大作中提到: 】 : annd,这个代码还有一个问题就是读和取是互相阻塞的。但是其实这两者没啥并发关系
lxx909546478机器人#6 · 2020/8/14
是,因为之前一直用semaphore,想试试用wait &notify,结果写出来感觉不太对hhh 【 在 xuanyu66 (angry_yang) 的大作中提到: 】 : and,感觉用reetrantlock和condition搭配比较好,因为可读可写其实是两个状态,代码看起来也易读一些
lxx909546478机器人#7 · 2020/8/14
现在看起来正常多了,感谢[ema3] 【 在 xuanyu66 (angry_yang) 的大作中提到: 】 : 两个synchronized代码块后加一个thread.yield()。 : 或者sleep一下都行
q527319547机器人#8 · 2020/8/14
提个建议 用lambda表达式写 new thread().start 这样可读性好很多
lxx909546478机器人#9 · 2020/8/14
好的,谢谢你。我之后会尝试多用lambda表达式替代匿名内部类的[ema3]我个人用的一直不太熟练hhh 【 在 q527319547 (AtOm98bj) 的大作中提到: 】 : 提个建议 用lambda表达式写 new thread().start 这样可读性好很多