【问题标题】:Shared item producers and consumer problem共享项目生产者和消费者问题
【发布时间】:2020-09-21 13:45:42
【问题描述】:

我有一种生产者消费者问题的味道(我找不到任何类似的问题并且搜索关键字用完了)哪里

  1. 消费者本身就是生产者。
  2. 生产的物品可以共享。
  3. 如果某个线程正在生产,其他线程会等待它完成并使用相同的生产项目。

我想出了一个解决方案,但我不知道如何测试它。是否有理论框架来验证此类问题的解决方案的正确性。也可以在不修改源代码的情况下测试这些解决方案

如果您对代码感兴趣,请在下面列出

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public class SharedItemProducer {

    /* testing parameters */
    static final int randMax = 1;
    static final Random R = new Random();
    static final int numThreads = 8;
    static final long produceDelay = 0;
    static final long maxRunTime = 5000;

    Integer item = 0;
    final Object waitingRoom = new Object();
    AtomicInteger wantToBeProducer = new AtomicInteger(0);

    public void produce() {
        log("entering produce");

        if (wantToBeProducer.compareAndSet(0, 1)) {
            log("i'm the producer. cur=%d", item);
            try {
                Thread.sleep(produceDelay);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            item = item + 1;
            synchronized (waitingRoom) {
                waitingRoom.notifyAll();
            }
            wantToBeProducer.set(0);
            log("done producing");
        } else {
            log("someone else is producing, waiting..");
            synchronized (waitingRoom) {
                try {
                    waitingRoom.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            log("wait complete");
        }
    }

    public static void main(String[] args) {

        long start = System.currentTimeMillis();

        /* run the tests */
        SharedItemProducer1 P = new SharedItemProducer1();
        for (int i = 0; i < numThreads; i++) {
            new Thread(() -> {
                while (true) {
                    P.produce();
                    try {
                        Thread.sleep(R.nextInt(randMax));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        /* limit time for tests */
        new Thread(() -> {
            try {
                Thread.sleep(maxRunTime);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.exit(0);
        }).start();
    }

    static boolean enableLog = false;
    static final String FMT = "[%s] [%s] ";

    public static void log(String info, Object... params) {
        if (!enableLog)
            return;
        Object[] pfParams = new Object[params.length + 2];
        System.arraycopy(params, 0, pfParams, 2, params.length);
        pfParams[0] = new Date();
        pfParams[1] = Thread.currentThread().getName();
        System.out.printf(FMT + info + "\n", pfParams);
    }
}

【问题讨论】:

  • 我建议仔细阅读the documentation of wait,尤其是为什么它应该在循环中执行的解释(而测试条件必须包含在同一个synchronized块中)。当其他线程已经在wait() 调用中时,当在synchronized 块之外做出进入等待状态的决定时,期望notify() 调用发生,这是一厢情愿的想法。跨度>

标签: java multithreading concurrency synchronization producer-consumer


【解决方案1】:

如果我理解正确,您是在寻求一种控制线程交错的方法,以便您可以验证可能的边缘情况和奇怪的情况。

我建议你看看 Baeldung - Testing Multi-Threaded Code in Java 看看是否有帮助。

它不仅讨论了测试并发代码的概念和策略,还提到了一些可能有用的工具,包括:

请看一下并尝试一下。

为了更好地测试您的代码,我还建议您对其进行更多模块化,这样您就可以单独测试生产者和消费者。

编辑:要提出测试用例,列出您可能希望在代码中验证的典型并发问题列表可能会有所帮助。请查看 CMU SEI 的这篇名为 Testing Concurrent Systems: Concurrency Defects, Testing Techniques, and Recommendations 的博文,了解详细列表。

【讨论】:

  • 感谢您指出文章。关于模块化,生产者和消费者是同一个线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 2011-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多