Алгоритм потребителя Java Threads Producer не работает должным образом - PullRequest
3 голосов
/ 30 мая 2011

Я пытаюсь изучить потоки, и поэтому я написал примерную проблему потребителя производителя, в которой производитель производит числа от 1 до 10, а потребитель должен их отображать.Но только потребитель отображает номер 1 и останавливается.

Как я уже сказал, программа написана плохо и может быть абсурдной, но все же я хочу выяснить причину, по которой все цифры от 1 до 10 не печатаются какЯ запомню лучше, когда я пишу код, а не из примеров.

Я использую две вариабельные области для отслеживания завершения действия Producres или потребителей, чтобы я мог выполнить другую.

/ getStatus (Consumer C) передает ссылку потребителю, чтобы производитель получал ссылку на потребителя ... и его можно использовать для определения статуса потребителя .. что это .. /

import java.lang.Math;
public class Hello{

public static void main(String args[]) {

    System.out.println("---1");
    new Consumer().start();

}

}

class Producer extends Thread{

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run(){

    System.out.println("---4");
    synchronized(this){

        do{

            System.out.println("---6");
            produce = produce+1;
            producerStatus = true;
            notify();
            consumerObj.consumerStatus = false;
            System.out.println("---9");
            count = count+1;

        }while(count<=10 && consumerObj.getStatus());

    }

}

public int getItem(){
    return produce;
}



public boolean getStatus(Consumer c){
    consumerObj = c;
    return producerStatus;

}

}

class Consumer extends Thread{

boolean consumerStatus = false;
int count =0;
public void run(){

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();
    try{
        System.out.println("---3");
        synchronized(p){
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        }
    }
    catch(Exception e){
            System.out.println("exception");
    }

    synchronized(p){
        try{
            while(p.getStatus(this) && count<=9 ){

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                p.wait();                   
                System.out.println("---10");

            }
        }
        catch(Exception e){
            System.out.println("exception");
        }

    }

}

public boolean getStatus(){

    return consumerStatus;

}
}

Вывод:

---1
---2
---3
---5
---4
---6
---9
---8
---7
the produced item is ----->1
---10

После ввода от .. Suraj .. Теперь программа работает нормально .. см. Ниже ..

import java.lang.Math;открытый класс Hello {

public static void main(String args[]) {

    System.out.println("---1");
    new Consumer().start();

}

}

class Producer extends Thread{

public int produce = 0;
public Consumer consumerObj =null;
int count = 1;
boolean producerStatus = false;

public void run(){

    System.out.println("---4");

        do{
            if(consumerObj.getStatus()){


            System.out.println("---6");
            produce = produce+1;
            System.out.println("---9 -- >produce is -->"+produce);
            producerStatus = true;
            synchronized(this){

            notify();
            System.out.println("---6.111");
            }

            consumerObj.consumerStatus = false;
            count = count+1;


            }


        }while(count<=10);


}

public int getItem(){

    return produce;

}

public boolean getStatus(Consumer c){

    consumerObj = c;
    return producerStatus;

}

}



class Consumer extends Thread{

boolean consumerStatus = true;
int count =1;
public void run(){

    System.out.println("---2");
    Producer p = new Producer();
    p.getStatus(this);
    p.start();//can a thread1 wait on an thread2 before the thread2 hass tarted and in this case wll notify on the scnd thread reaally notify therad1 ..
    try{
        System.out.println("---3");
        synchronized(p){
            System.out.println("---5");
            p.wait();

            System.out.println("---8");
        }
    }
    catch(Exception e){
            System.out.println("exception");
    }


        try{
            while(count<=10 ){

                System.out.println("---7");
                int consume = p.getItem();
                System.out.println("the produced item is ----->"+consume);
                count = count+1;
                p.producerStatus  = false;
                consumerStatus = true;
                synchronized(p){
                p.wait();   
                System.out.println("---10");        
                }


            }
        }
        catch(Exception e){
            System.out.println("exception");
        }


}

public boolean getStatus(){

    return consumerStatus;

}

}

Ответы [ 3 ]

3 голосов
/ 30 мая 2011

OK.Программа неверна.

  1. Поток потребителя приходит и ожидает блокировки.
  2. Первая итерация в цикле производителя вызовет notify, но при этом освобождает блокировку, поскольку цикл whileвнутри синхронизированного блока.Он будет повторяться 10 раз без снятия блокировки и в конечном итоге будет вызывать уведомление 10 раз непрерывно.
  3. Но Потребитель может только разбудить один раз, а во второй раз, когда потребитель вызывает wait (), он продолжает ждать, так как нет никого.вызвать notify сейчас (так как все 10 итераций источника завершены)

Таким образом, проблема в том, что потребительский поток ожидает, но нет никого, чтобы уведомить его, так как производитель завершил все 10итерации в 1 выстрел.

0 голосов
/ 30 августа 2011

Вы должны использовать BlockingQueues. см http://www.javamex.com/tutorials/synchronization_producer_consumer_2.shtml.

Вышеуказанная реализация неэффективна, и она заставляет всех потребителей блокировать ее. с несколькими очередями вы можете предотвратить блокировку всех потребителей. Вы можете найти примеры в Google. Java.util.concurrent Используйте это, это есть причина.

0 голосов
/ 30 мая 2011

в Producer, вы устанавливаете

consumerObj.consumerStatus = false;

и немедленно проверьте это значение в состоянии цикла. Петли заканчиваются после 1 цикла. После

count = count+1;

Вам следует подождать («потребление»).

try{
    this.wait();
} catch (Exception e) {
    e.printStackTrace();
}

Та же проблема в Потребителе. Последняя вещь в цикле должна быть

p.wait();
...