Współbieżność Producent-Konsument.

0

Witam.

Od niedawna próbuję nauczyć się wpółbieżności w Javie i postawiono mi takie zadanie (treść podana niżej)... Niestety nie bardzo wiem jak się za to zadanie zabrać... Czy mógłby mi podpowiedzieć ewentualnie napisać jakiś szkic klasy?

Kod, działający w wątku A czyta z pliku ../Towary.txt informacje o towarach w postaci:

id_towaru waga

tworzy obiekty klasy Towar, zawierające przeczytane informacje oraz wyprowadza na konsolę informacje o liczbie utworzonych obiektów. Informacja ma być wyprowadzana co 200 obiektów w postaci:

utworzono 200 obiektów
utworzono 400 obiektów
utworzono 600 obiektów
itd.

Kod działający równolegle w innym wątku (B) sięga po te obiekty, sumuje wagę towarów i wyprowadza na konsolę informację o przeprowadzonym sumowaniu co 100 obiektów np.:
policzono wage 100 towarów
policzono wage 200 towarów
policzono wage 300 towarów
itd.
Na końcu podaje sumaryczną wagę wszystkich towarów.

Uwagi:

Plik powinien zawierać co najmniej 10 tys. opisów towarów (należy sobie go wygenerować programistycznie, ale na boku, nie w tym programie),  nazwa pliku (wraz ze ścieżką) jest obowiązkowa , proszę nie dołączać tego pliku do projektu..
Zapewnić synchronizację i koordynację pracy obu wątków.
Forma wydruku na konsoli jest obowiązakowa
Wszystkie klasy w programie winny być publiczne (w różnych plikach)
Wykonanie programu winno zaczynać się w metodzide main()  obowiązakowej klasy Main.
Plik winien znajdować się w nadkatalogu projektu (czyli w katalogu workspace'u)

Z góry dzięki.


Update: Popróbowałem coś zrobić samemu.. wydaje mi sie ze nie trzyma to wszystko sie kupy ale wstawie ... moze to bedzie jakis punkt wyjscia:



import java.io.FileNotFoundException;
import java.util.LinkedHashMap;
import java.util.Map;


public class Main {
	
private static boolean values=false;
	private static Map<Integer,Double>valuesMap=new LinkedHashMap<>();
  public static void main(String[] args) {
	Thread watekA=new Thread("Watek A") {
		@Override 
		public void run() {
			try {
				while(values) {
					wait();
				}
			}catch(InterruptedException ex) {
				ex.printStackTrace();
			}
			while(/*sa nastepne wiersze z danymi*/) {
				//1. wloz do mapy
				//2. ustaw values=true
				//3.notifyAll()
			}
		}
	};
	Thread watekB=new Thread("Watek B") {
		@Override
		public void run() {
			try {
				while(!values) {
					wait();
				}
			}catch(InterruptedException ex) {
				ex.printStackTrace();
			}
			while(valuesMap.isEmpty()==false) {
				// 1. wykonaj obliczenia i usuwaj pojedyncze elmenty z mapy
			}
			//tutaj mapa jest juz pusta
			values=false;
			notifyAll();
		}
	};
	
  }
}

1

poczytaj o kolejkach blokujących - to jest coś czego możesz użyć w tym zadaniu
http://www.baeldung.com/java-blocking-queue

0

Dzięki zerknę ale wydaje mi się że zadanie mszę wykonać bez użycia zaimplementowanych już "rzeczy" :/

1

Ja bym stworzył tutaj 3 klasy.
1 kontener do którego będą wrzucane / pobierane dane. W tej klasie zaimplementować metody do tych operacji.
2. Klasa (wątek) pobierający dane z pliku i tworzący obiekty, przekazujesz jej kontener do którego będzie wrzucać obiekty i wypisywać na konsole informację, jak już wszystko sczyta niech wrzuci tam np null.
3. Klasa (wątek) pobierający dane z kontenera dopóki nie sczyta nulla, przelicza i wyświetla komunikaty.


class Kontener {

  Object obj = null;
  boolean newObj = false;

  //  - wywołuje Dodawacz
  synchronized void dodajObiekt(Object o) {
    while (newObj == true) {
      try {
        wait();
      } catch(InterruptedException exc) {}
    }
    obj= o;
    newObj = true;
    notifyAll();
  }

  // wywoluje Pobieracz
  synchronized Object getObj() {
    while (newObj == false) {
      try {
        wait();
      } catch(InterruptedException exc) {}
    }
    newObj = false;
    notifyAll();
    return obj;
  }

}


class Pobieracz extends Thread {

  Kontener kont;

  Pobieracz(Kontener kont) {
    this.kont = kont;
  }

  public void run() {
   Object o = kont.getObj();
    while(o != null) {
       //przetwarzasz dane
      System.out.println("wypisuje przetrworzone dane");
      o = kont.getObj();
      }
  }

}


class Dodawacz extends Thread {

  Kontener  kont;

  Dodawacz(Kontener kont)  {
    this.kont = kont;
  }

  public void run() {

//tworzysz obiekty, jesli to ostatni to posyłasz null
      kont.add(obiekt);
    }
  }

}


public class Main {

   public static void main(String[] args) {
     Kontener k = new Kontener();
     Thread t1 = new Dodawacz(k);
     Thread t2 = new Pobieracz(k);
     t1.start();
     t2.start();
   }
}

Kodu nie sprawdzałem więc może się nie kompilować przez jakieś literówki ale idee łapiesz. Ponazywaj to jakoś sensownie i możesz rozbić to na więcej klas i uczynić ten program bardziej obiektowym. Możesz dodać klasę Licznik, coś do przetwarzania tekstu na obiekty, inną do wczytywania ich, jeszcze jedną do wypisywania. Trzymając się warunków w zadaniach Twoje klasy łamią zasadę SRP.

No i stwórz klasę Towar, pozamieniaj tam gdzie Object w moim kodzie. Nie mieszaj nazw angielskich z polskimi tak jak ja to zrobiłem.

http://tutorials.jenkov.com/java-concurrency/index.html - popatrz tutaj ale o ile nie musisz to zdecydowanie lepiej skorzystać z klas dostarczanych w java.util.concurrent niż samemu takie rzeczy implementować. Współbieżność to twardy orzech ^.^

1 użytkowników online, w tym zalogowanych: 0, gości: 1