Koordynacja wątków użycie wait()

0

Witam

Staram się opanować wielowątkowość. I mam problem z koordynacją.
Chciałbym aby czytacz i obliczacz współpracowały ze sobą , czytacz niech odczytuje po 200 towarów(i tworzy z nich obiekty) z pliku. Natomiast obliczacz niech równolegle coś tam liczy z odczytanych (w tym przykładzie danych o towarach ) po 100.
Czyli czytacz tworzy 200 obiektów, obliczacz niech liczy po 100, gdy obiekty się kończą niech czytacz doczytuje.

I nie rozumiem chyba za bardzo działania synchronizacji, (Prośba o prze-edukowanie) .
Bo wait() mogę tylko zgłosić z sekcji krytycznej , więc rygluje klasę Towar w bloku synchronizowanym w metodzie run żeby drugi wątek nie miał dostępu do statycznej kolekcji obiektów towarów.
Efekt powinien być taki według mnie że póki nie zwolnię rygla metody statyczne z klasy Towar są blokowane.
Więc gdy zrobię taką samą synchronizacje w bloku instrukcji w obliczaczu będzie ok.
Ale jednak coś jest nie tak, bo gdy wrzucam wait z czytacza otrzymuje "illegal monitor state exception"

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;

public class Czytacz extends Thread {

	boolean read200 = false;
	String txt = null;
	int licznik = 0;
	
	
	public void run(){
		
		try {
			FileReader fr = new FileReader("towar.txt");
			LineNumberReader lr = new LineNumberReader(fr);
			synchronized(Towar.class){
			while(!read200){
				Towar t = new Towar();
				txt = lr.readLine();
				t.id = Integer.parseInt( txt.substring(0, txt.indexOf(' ')) );
			    t.waga = Double.parseDouble( txt.substring( txt.indexOf(' ') ) );
			   
				Towar.add(t);
				licznik++;
					if( (licznik%200) == 0){
						read200 = true;
						wait();
					}
			    }
			}
		}  catch (IOException | InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			read200 = true;
		}
	    
				
	
	}
}



Nie rozumiem tego ,dlatego proszę niech ktoś mi nie wrzuca kodu który działa ...tylko mi wytłumaczy (najlepiej na przykładzie) jak obchodzić się z koordynacją wątków.

Z góry dziękuje za pomoc i zainteresowanie.

0

Witam
w dużym stopniu poradziłem sobie (Ale wciąż mam problem) , odpowiedź jest prosta: wątek wstrzymujemy na bazie rozwiązania:

  while (warunek_działania_wątku) {
     try {
       synchronized(this) {
         while (suspended)  // warunek wstrzymania wątku
           wait();
       }
     } catch(InterruptedException exc) { return; }
     // ... praca wątku.
   }

Być może ktoś będzie kiedyś zastanawiał się nad tym samym problem , i ten post mu pomoże

Natomiast nie wiem jak z innego wątku wznowić zatrzymany wątek , bo musiał bym zsynchronizować w tym innym wątku blok instrukcji względem obiektu zatrzymanego wątku( a w nim zmienić "suspended" i wywołać notify() ), a nie chcę wysyłać między wątkami referencji do siebie bo robi to się mało sensowne moim zdaniem . Jakaś propozycja?

Pozdrawiam

1

Tak. Opisz swój problem, a nie wątpliwej jakości rozwiązanie. Bo póki co nie wiadomo co chcesz osiągnąć, a tylko jak próbujesz to osiągnąć (i że nie działa).
Ogólnie synchronizacja powinna odbywać się na jakimś dzielonym zasobie, toteż oba wątki mają dostęp do tego zasobu i mogą sobie robić wait/notify. Domyślam się że twój błąd polega na tym że próbujesz tu używać jakiejś klasy ze statycznymi metodami i polami, zamiast stworzyć obiekt związany z przechowywaniem Towarów.
W ten sposób wszystkie wątki mają dostęp do obiektu CommoditiesCollection i mogą się na nim synchronizować.

1

Użyj BlockingQueue np. LinkedBlockingQueue. Ustaw rozmiar kolejki na 1 element i trzymaj w niej pakiety po 100 danych.

/* czytacz */
while (!this.isInterrupted()) {
    /* odczytujemy pakiet stu danych */
    pakiet = czytaj();

    try {
        /* wrzucamy pakiet do kolejki, wątek poczeka aż w kolejce będzie
         * miejsce (aż będzie pusta bo rozmiar ustawiliśmy na 1) */
        kolejka.put(pakiet);
    } catch (InterruptedException e) {
        break;
    }
}

/* procesor */
while (!this.isInterrupted()) {
    try {
        /* pobieramy pakiet danych z kolejki
         * wątek poczeka aż w kolejce znajdzie się pakiet */
        pakiet = kolejka.take();
    } catch (InterruptedException e) {
        break;
    }
    licz(pakiet); // wykonujemy obliczenia
}

Możesz jeszcze dosterować odpowiednio wielkość pakietu czy ilość pakietów w kolejce tak, aby narzut związany z synchronizacją zrównoważyć z czasem po jakim dane trafią do kolejki od momentu ich odczytania.

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