несколько производителей и потребителей, используя многопоточность в JAVA - PullRequest
0 голосов
/ 10 июля 2020

Я застрял в этом вопросе по поводу вопроса нескольких производителей-потребителей. Моя цель - написать шесть потоков, которые будут действовать как A, B, ..., F, и позволить программе продолжать печать вечно.

Щелкните здесь, чтобы увидеть изображение: щелкните

Каждая пара узлов, связанных со стрелкой, соответствует паре производителей-потребителей (или, скажем, buffer ). Размер буфера составляет 2 , и изначально только A владеет 2 токенами. Я уже пробовал A -> B -> D -> F. Код выглядит следующим образом:

class Cookies   
{
    private int cookiesNo;
    private int buffer=0;

    public synchronized void put (int cNo, String sender, String receiver)
    {
        while (buffer==2)
        {
            try
            {
                wait();
            }
            catch (InterruptedException e){}
        }
        System.out.println(sender+" put the "+cNo+"th cookie to "+receiver);
        cookiesNo= cNo;
        buffer++;
        notify();
    }
    public synchronized void eat (int cNo, String sender, String receiver)
    {
        while (buffer==0)
        {
            try {
                wait();
            }
            catch (InterruptedException e){}
        }
        System.out.println(sender+" put the "+cNo+"th cookie to "+receiver);
        cookiesNo= cNo;
        buffer--;
        notify();
    }
}
class DPut implements Runnable  
{
    Cookies cookies;
    DPut(Cookies cookies)
    {
        this.cookies=cookies;
    }
    public void run()
    {
        for (int i=1; i<=10000; i++)
        {
            cookies.put(i, "D", "F");
        }
    }
}
class DEat implements Runnable  //human
{
    Cookies cookies;
    DEat(Cookies cookies)
    {
        this.cookies=cookies;
    }
    public void run()
    {
        for (int i=1; i<=10000; i++)
        {
            cookies.eat(i, "B", "D");
        }
    }
}
class APut implements Runnable  
{
    Cookies cookies;
    APut(Cookies cookies)
    {
        this.cookies=cookies;
    }
    public void run()
    {
        for (int i=1; i<=100; i++)
        {
            cookies.put(i, "A", "B");
        }
    }
}
public class practice
{
    public static void main(String[] args) 
    {
        Cookies cookies= new Cookies();
        DPut dput= new DPut(cookies);
        DEat deat= new DEat(cookies);
        APut aput= new APut(cookies);
        Thread ddog= new Thread(deat);
        Thread dmaster= new Thread(dput);
        Thread amaster= new Thread(aput);

        amaster.start();
        ddog.start();
        dmaster.start();

    }
}

Вывод (я снимаю скриншоты в начале и середине):

click1 click2

Я пытался представить его как хозяин (производитель), собака (потребитель) и повар ie (продукт). Хозяин ставит повар ie и собака его ест.

Мои проблемы:

  1. Результат выглядит как первое изображение (AtoB и BtoD) в начале 100 печенек . Потом получилось фото два (BtoD & DtoF) до 10 тысяч. Как я могу это исправить? Я хочу, чтобы он также запустил AtoB, но он просто остановился ...
  2. Я не знаю, как начать с A и F, поскольку у них два входа или два выхода.
  3. Моя стратегия верна? Я написал код на основе сценария с одним производителем и потребителем.

Я новичок в многопоточности, поэтому, пожалуйста, расскажите мне о моих ошибках. Спасибо вам огромное!

1 Ответ

0 голосов
/ 10 июля 2020

Во-первых, хотя «синхронизированный» по-прежнему действителен для мьютекса, он устарел на 15 лет для сигнализации. Если вы хотите сделать ожидание / уведомление, используйте реентерабельные блокировки и условия await / signal [All].

Notify () пробуждает только 1 поток, и это может быть неправильный поток, потому что у вас его нет условие для сигнала. Последний поток размещения, устанавливающий для буфера значение 2 (полный), может уведомить другой поток размещения, тогда больше не будет уведомлений, чтобы разбудить пожирателя.

Старым способом было бы использовать notifyAll (), и это будет работать, хотя разбудит всех и вызовет много споров, чтобы получить синхронизированный файл ни за что, кроме одного или двух потоков. Вот почему вам следует предпочесть реентерабельную блокировку с двумя условиями (не пусто / не заполнено).

Это в значительной степени основы, лежащие в основе очереди блокировки массива.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...