当前位置: 首页 > 知识库问答 >
问题:

多个生产者和消费者多线程Java不能按预期工作

卢聪
2023-03-14

我正在与Java一起研究生产者-消费者问题的多生产者和消费者用例。代码在GitHub上。同样的实现适用于单个生产者和消费者用例,但对于多生产者和消费者用例却表现得很奇怪。

我有一些关于输出的问题:

一开始,所有生产者和一个消费者都有锁:

Producer t1 has lock
t5 produced 1, integerQueue: [1]
Producer t5 notifiedAll
  1. 我想所有的线程都应该竞争锁,并且最多应该有一个线程拥有所有时间的锁?是不是所有的制作人都共用这个锁?当生产者线程t1持有锁时,使用者线程t5是如何获得锁的?

它运行一段时间后,另一个怪异的现象出现了:

Producer t5 has lock
t5 produced 10, integerQueue: [8, 9, 10]
Producer t5 notifiedAll

Producer t5 has lock
t5 produced 11, integerQueue: [8, 9, 10, 11]
Producer t5 notifiedAll

Consumer t8 has lock
t8 consumed 8, integerQueue: [9, 10, 11]
Consumer t8 notified All

Consumer t8 has lock
t8 consumed 9, integerQueue: [10, 11]
Consumer t8 notified All

非常感谢任何帮助。

共有1个答案

闻安宜
2023-03-14

您正在使用Producer5runnable的单个实例,并将其多次提交给执行服务。

    Producer5 producer = new Producer5(queue, maxCapacity);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);
    pool.execute(producer);

因此,单个Producer5实例中的ThreadName字段将被覆盖几次,并且不再有用(它将不再打印出实际运行的线程的名称,此外,它需要volatile才能被多个线程正确更新--对于正确的定义)。

  System.out.println(String.format("\nProducer %s has lock",
    threadName // this will be the name of the last thread that entered `run`, 
              // they all share the same instance 
  )); 

如果同一runnable实例包含可变状态,则不要重用该实例。为每个执行线程创建一个单独的实例

当生产者线程t1持有锁时,消费者线程t5是如何获得锁的?

运行此代码的仍然是线程t1,但ThreadName字段同时已被线程T5更新。极具误导性的输出。

除了一个生产者和消费者之外,似乎所有的线程都死了,这两个线程正在彼此之间切换锁。

线程都还活着,但只有两个threadname字段存在,线程一直在轮流更新这些字段(在run方法的顶部),最后确定某个值。所有线程现在只打印该值。

 类似资料:
  • 我有两个线程的问题,似乎没有正确同步。我基本上有一个布尔值名为“已占用”。当没有线程启动时,它被设置为false。但是当一个线程启动时,线程集被占用是真的,我有一个类,它有线程(run),它们调用下面的函数。 这是一个模拟银行的示例,它接收一个金额(初始余额),然后随机执行取款和存款。我的教授提到了一些关于从取款线程到存款线程的信号?这是怎么回事?在提取线程中,它应该运行到余额为2低,并等待存款线

  • 我有一个使用ActiveMQ的消息队列。web请求用persistency=true将消息放入队列。现在,我有两个消费者,它们都作为单独的会话连接到这个队列。使用者1总是确认消息,但使用者2从不这样做。 JMS队列实现负载平衡器语义。一条消息将被一个使用者接收。如果在发送消息时没有可用的使用者,它将被保留,直到有可以处理消息的使用者可用为止。如果使用者接收到一条消息,但在关闭之前没有确认它,那么该

  • 我有三根线。线程1(T1)是生成器,它生成数据。线程2和线程3(T2和T3)分别等待T1的数据在单独的循环中处理。我正在考虑在线程之间共享BlockingQueue,并通过调用“Take”让T2和T3等待。

  • 问题内容: 因此,我已经看到了许多在Go中实现一个消费者和许多生产者的方法-Go 并发中的经典fanIn函数。 我想要的是fanOut功能。它以一个通道作为参数,它从中读取一个值,并返回一个通道片,该通道将这个值的副本写入其中。 有没有正确/推荐的方法来实现这一目标? 问题答案: 您几乎描述了执行此操作的最佳方法,但这是执行此操作的一小段代码示例。 去游乐场:https : //play.gola

  • 本文向大家介绍java 中多线程生产者消费者问题详细介绍,包括了java 中多线程生产者消费者问题详细介绍的使用技巧和注意事项,需要的朋友参考一下 java 中多线程生产者消费者问题 前言: 一般面试喜欢问些线程的问题,较基础的问题无非就是死锁,生产者消费者问题,线程同步等等,在前面的文章有写过死锁,这里就说下多生产多消费的问题了 这个是jdk版本1.5以上的多线程的消费者生产者问题,其中优化的地

  • 本文向大家介绍Java多线程生产者消费者模式实现过程解析,包括了Java多线程生产者消费者模式实现过程解析的使用技巧和注意事项,需要的朋友参考一下 单生产者与单消费者 示例: 执行结果如下: 多生产者与多消费者 这种模式下,容易出现“假死”,也就是全部线程都进入了 WAITNG 状态,程序不在执行任何业务功能了,整个项目呈停止状态。 示例: 运行结果如图: 分析: 虽然代码中通过 wait/not