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, botów: 0