Zadanie polega na wczytaniu z pliku danych dotyczących towarów (w jednym wątku) - każda linia pliku txt zawiera dwie dane: id_towaru waga_towaru - wątek powinien informować o utworzeniu odpowiedniej liczby towarów (np. co 200).
Drugi równoległy wątek powinien sumować wagę tych towarów, informować o zważeniu odpowiedniej liczby towarów (np. co 100) i na koniec podawać łączną wagę wszystkich towarów.
Moje rozwiązanie oparłem o problem producent - konsument. Wątek wczytujący towar pobiera go z pliku i "wrzuca" do schowka. Wątek ważący pobiera towar ze schowka i pobiera jego wagę. Wszystko wygląda OK, ale wątek ważący nie kończy pracy i nie podaje łącznej sumy towarów (a dokładniej - robi to od czasu do czasu). Gdzie tkwi błąd?
Kody
Klasa Main:
public class Main {
public static void main(String[] args) {
Schowek s = new Schowek();
Wczytanie wczytanie = new Wczytanie(s);
Wazenie wazenie = new Wazenie(s);
Thread wczytaj = new Thread (wczytanie);
Thread zwaz = new Thread (wazenie);
wczytaj.start();
zwaz.start();
}
}
Klasa Towar:
public class Towar {
int idTowaru;
double wagaTowaru;
static int liczbaTowarow = 0;
public Towar (int i, double w) {
idTowaru = i;
wagaTowaru = w;
++liczbaTowarow;
}
public double getWagaTowaru() {
return wagaTowaru;
}
}
Klasa Schowek:
public class Schowek {
Towar towar;
boolean ready = false;
synchronized Towar get() {
try {
while(!ready)
wait();
} catch (InterruptedException exc) { return null; }
ready = false;
return towar;
}
synchronized void put(Towar t) {
towar = t;
ready = true;
notify();
}
}
Klasa Wczytanie:
import java.io.File;
import java.util.Scanner;
import java.util.StringTokenizer;
public class Wczytanie implements Runnable {
private Towar towar;
private Schowek schowek;
volatile static boolean czyJestJeszczeTowar = true;
public Wczytanie(Schowek schowek) {
super();
this.schowek = schowek;
}
@Override
public void run() {
try {
Scanner scan = new Scanner(new File("../Towary.txt"));
while (scan.hasNextLine()) {
StringTokenizer st = new StringTokenizer (scan.nextLine());
int a = Integer.parseInt(st.nextToken());
double b = Double.parseDouble(st.nextToken());
towar = new Towar(a, b);
schowek.put(towar);
if (Towar.liczbaTowarow%200 == 0) System.out.println("utworzono " + Towar.liczbaTowarow + " obiektów");
}
czyJestJeszczeTowar = false;
scan.close();
}
catch (Exception exc) {
System.out.println("Brak pliku");
}
System.out.println("Razem utworzono: " + Towar.liczbaTowarow + " obiektów");
}
}
Klasa Wazenie:
public class Wazenie implements Runnable {
private Towar towar;
private Schowek schowek;
double waga = 0;
public Wazenie(Schowek schowek) {
super();
this.schowek = schowek;
}
@Override
public void run() {
while (Wczytanie.czyJestJeszczeTowar == true) {
towar = schowek.get();
waga += towar.getWagaTowaru();
if (Towar.liczbaTowarow%100 == 0) {
System.out.println("obliczono wage " + Towar.liczbaTowarow + " towarów");
}
}
System.out.println("Łączna waga wszystkich towarów: " + waga);
}
}
Drugi problem to prezentacja wyników. W wynikach drugi wątek podaje nierówne dane dotyczące ważenia (103 towary poniżej), a niektóre dane w ogóle pomija (brak informacji o zważeniu 200 towarów):
obliczono wage 103 towarów
utworzono 200 obiektów
obliczono wage 300 towarów
utworzono 400 obiektów
obliczono wage 400 towarów
Razem utworzono: 444 obiektów