Problem z wątkami (Java)

0

Witam,
piszę program który ma symulować garaż (parking) i natrafiłem na taki problem, że mój garaż nigdy nie zapełni się samochodami do końca w sensie takim zeby inne samochody czekały przed garażem. W metodzie brama3wypusc próbowałem zrobić wait() (na różne sposoby) ale wtedy źle wyświetlało liczbę wolnych miejsc. W programie głównym podawałem liczbę miejsc w garażu 2 a po zakończeniu działania programu wyświetla że liczba wolnych miejsc jest równa 4. Proszę o każdą sugestie / podpowiedź jak mogę sobie z tym poradzić.
Oto dwie klasy które wypociłem.
Klasa garaż:

import java.util.concurrent.TimeUnit;




public class Garaz_2 {
	
	int liczbaMiejsc;
	int wolneMiejsca;
	int czas = 1;
	
	public Garaz_2 (int liczbaMiejsc) {
		this.liczbaMiejsc = liczbaMiejsc;
		wolneMiejsca = liczbaMiejsc;
	}
	
	synchronized public void brama1wpusc (int nrPojazdu) {
				
		if (this.wolneMiejsca > 0) {
			notifyAll();
			System.out.println("WJEZDZA <- " + nrPojazdu);
			
			this.wolneMiejsca--;	
			System.out.println("WJAZD Liczba miejsc na parkingu: " + liczbaMiejsc + ". Liczba wolnych miejsc: "+this.wolneMiejsca);
		}
		else if (this.wolneMiejsca==0) {     		  //jesli nie ma miejsc watek ma czekac
			System.out.println("Samochod_" + nrPojazdu + " Czeka");
			try {
				wait();
			} catch (InterruptedException e) {

				e.printStackTrace();
			}
		}
		
	}
	
	synchronized public void brama3wypusc(int nrPojazdu) {
	
	
		 wolneMiejsca++;
		    System.out.println("WYJEZDZA -> " + nrPojazdu );
		    
			System.out.println("WYJAZD Liczba miejsc na parkingu: " + liczbaMiejsc + ". Liczba wolnych miejsc: "+this.wolneMiejsca);
		
		
		
	}

} 

Klasa samochód:

 
import java.util.concurrent.TimeUnit;


public class Samochod_2 extends Thread{

	int nrPojazdu;
	final int LICZBA_WYKONAN = 2;
	Garaz_2 garaz_2;
	int czas = 1;
    
	public Samochod_2 (int i, Garaz_2 garaz_2) {
		nrPojazdu = i;
		this.garaz_2 = garaz_2;
	}
	
	public void run () {
		
		for (int licznik = 0; licznik < LICZBA_WYKONAN; licznik ++) {

			
				jedz(nrPojazdu);
				wjedz_lub_czekaj(nrPojazdu);
				wyjedz(nrPojazdu);
				
		}
	}
	

	
	
	public void jedz (int i){
		
		System.out.println("Samochod "+ i + " jedzie");
		try {
			TimeUnit.SECONDS.sleep(czas);
		} catch (InterruptedException e) {

			e.printStackTrace();
		}
	}
	
	public void wjedz_lub_czekaj (int i){
			garaz_2.brama1wpusc(i);
		}
		

	public void wyjedz (int i){
		garaz_2.brama3wypusc(i);
	}
		
}
0

A ile wątków uruchamiasz na raz?

0

No chyba odpalam tylko jeden wątek.
Od razu przepraszam za moje głupie pytania. Ale to znaczy ze na przykład powinienem zrobić wjazd do garażu i wyjazd jako dwa osobne wątki i wtedy jak garaż będzie pełen to zrobić wait() w wątku wjazdowym jak pełen nie będzie to wait() w wątku wyjazdowym?

Tak wygląda klasa główna:

public class Program_Glowny {

	
	public static void main(String[] args) {
	
		int liczbaSamochodow =4;
		int liczbaMiejsc = 2;
		
		Garaz_3 garaz_3 = new Garaz_3(liczbaMiejsc);
		for (int licznik = 0; licznik < liczbaSamochodow; licznik ++) {
			   new Samochod_2(licznik, garaz_3).start();
			  
		}

	}

	
	
	
} 
1

Nie. Problem leży w tym fragmencie:

jedz(nrPojazdu);
wjedz_lub_czekaj(nrPojazdu);
wyjedz(nrPojazdu);

Jeżeli to działa w pętli i w ramach jednego wątku to zobacz co się dzieje:

  • samochód 1 jedzie - wątek czeka sekundę
  • garaż sprawdza czy są wolne miejsca - są wpuszcza
  • ilość wolnych miejsc - 1
  • samochód wyjeżdża
  • ilość wolnych miejsc + 1
  • kolejny samochód

W takim układzie na raz tak naprawdę obsługiwany jest tylko jeden samochód. W dodatku pętla jest tak skonstruowana, że nie ma szans na to by dwa samochody trafiły do garażu w tym samym czasie.

Jak to poprawić.

  • jest wiele samochodów - wątków i jeden garaż - zasób wymagający synchronizacji
  • uruchamiasz poszczególne samochody najlepiej za pomocą klasy Executor
  • przerób metodę jedzie tak by jazda trwała losowy czas
  • przerób metodę wjedźLubCzekaj tak by po wjechaniu samochód parkował przez pewien losowy czas

Na koniec możesz pobawić się jeszcze w kolejkowanie samochodów tak by pierwszy wjeżdżający, który się nie załapie na wolne miejsce jako pierwszy wjechał po zwolnieniu miejsca.

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