Współbieżność, pomoc przy programie

Współbieżność, pomoc przy programie
0

Witam

Potrzebuję pomocy przy programie, w pewnym momencie się zawiesza. Lisitngu nie wrzucą bo to ponad 400 linii, ale jeśli ktoś chciałby mi pomóc to mogę wysłać. Program robię na podstawie TIJ, ale w jednym miejscu i w książka nie pomaga.

Pozdrawiam

0

A może ktoś <ort>napiszę </ort>mi <ort>napiszę </ort>czy istnieją jakieś narzędzia <ort>nie odpłatne </ort>przy pomocy<ort>, </ort>których mogę wykryć błędy programu współbieżnego, używam NetBeans, może są jakieś wtyczki, jednak ja nic nie znalazłem. Próbowałem zainstalować findbug'a<ort> </ort>ale bezskutecznie, chyba link już jest martwy.

0

Wszystkie klasy mam w jednym pliku, więc wystarczy wrzucić, włączyć i przejrzeć listing:

Kopiuj
import java.text.SimpleDateFormat;
import java.util.concurrent.*;
import java.util.*;

class Car {
  private final int id;
  private boolean
    cleaned = false, washed = false, waxed = false,
    needCleaning = false, needWashing = false, needWaxing = false,
    cleaningInProgress = false, washingInProgress = false, waxingInProgress = false,
    cleaningDone = false, washingDone = false, waxingDone = false;
  private final String arrivedTime;
  private static Random rand = new Random();
  public Car(int idn)  { 
      id = idn;
      needCleaning = rand.nextBoolean();
      needWashing = rand.nextBoolean();
      needWaxing = rand.nextBoolean();
      arrivedTime = DateUtils.now();
      cleaningDone = ! needCleaning;
      washingDone = ! needWashing;
      waxingDone = ! needWaxing;

  }
  public Car()  {
      id = -1;
      arrivedTime = DateUtils.now();
  }
  public synchronized int getId() { return id; }

  public synchronized void waxing() {
      waxingInProgress = true;
  }

  public synchronized void cleaning() {
      cleaningInProgress = true;
  }

  public synchronized void washing() {
      washingInProgress = true;
  }

  public synchronized void waitForWashing() throws InterruptedException {
      while(! cleaningDone) {
          wait();
      }
  }

  public synchronized void waitForWaxing() throws InterruptedException {
      while (! washingDone || ! cleaningDone) {
          wait();
      }
  }

  public synchronized void waitIfAnyServiceIsProcessingCar() throws InterruptedException {
      while (washingInProgress || cleaningInProgress || waxingInProgress) {
          wait();
      }
  }

  public synchronized void waitForAllServiceFinished() throws InterruptedException {
          while (! cleaningDone || ! washingDone || ! waxingDone) {
              wait();
          }
  }

  public synchronized void cleaned() {
      cleaned = true;
      cleaningInProgress = false;
      cleaningDone = true;
      notifyAll();
  }
  public synchronized void waxed() {
      waxed = true;
      waxingInProgress = false;
      waxingDone = true;
      notifyAll();
  }
  public synchronized void washed() {
      washed = true;
      washingInProgress = false;
      washingDone = true;
      notifyAll();
  }

  public synchronized boolean needCleaning() {
      return needCleaning;
  }

  public synchronized boolean needWashing() {
      return needWashing;
  }

   public synchronized boolean needWaxing() {
      return needWaxing;
  }

    @Override
    public synchronized String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("------------------------------------");
        builder.append("\n");
        builder.append("Informacje na temat obsługi pojazdu o id: " + id);
        builder.append("\n");
        builder.append("Czas przybycia: " + arrivedTime);
        builder.append("\n");
        builder.append("Czas odjazdu: " + DateUtils.now());
        builder.append("\n");
        builder.append("------------------");
        builder.append("\n");
        builder.append("Zamówiony pakiet: ");
        builder.append("\n");
        builder.append("------------------");
        builder.append("\n");
        builder.append("Sprzątanie: ");
        builder.append(needCleaning ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("Mycie: ");
        builder.append(needWashing ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("Woskowanie: ");
        builder.append(needWaxing ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("------------------");
        builder.append("\n");
        builder.append("Wykonany serwis: ");
        builder.append("\n");
        builder.append("------------------");
        builder.append("\n");
        builder.append("Sprzątanie: ");
        builder.append(cleaned ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("Mycie: ");
        builder.append(washed ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("Woskowanie: ");
        builder.append(waxed ?  "Tak"  : "Nie");
        builder.append("\n");
        builder.append("------------------");
        builder.append("\n");
        builder.append("Pojazd o id :" + id + " opuścił myjnię.");
        builder.append("\n");
        builder.append("------------------------------------");
        builder.append("\n");
        return builder.toString();
    }
}

class CarQueue extends LinkedBlockingQueue<Car> {
}

class CarWashEntrance implements Runnable {
  private CarQueue carQueue;
  private int counter = 0;
  private boolean isOpen = false;
  public CarWashEntrance(CarQueue cq) { carQueue = cq; }
  public void run() {
   open();
    try {
      while(isOpen()) {
        TimeUnit.MILLISECONDS.sleep(1500);
        Car c = new Car(counter++);
        System.out.println("Pojazd o id: " + c.getId() + " znajduje się w kolejce do myjnii.");
        carQueue.put(c);
        
      }
    } catch(InterruptedException e) {
    }
    System.out.println("Brama wjazdowa została zamknięta.");
  }
  public synchronized boolean isOpen() { return isOpen; }
  public synchronized void open() {
      isOpen = true;
      System.out.println("Brama wjazdowa została otwarta.");
  }
  public synchronized void close() { isOpen = false; }
}

class CarWashLine implements Runnable {
  private CarQueue waitingQueue, finishingQueue, processingQueue;
  private Car car;
  private ServicePool servicePool;
  public CarWashLine(CarQueue cq, CarQueue fq, ServicePool rp){
    waitingQueue = cq;
    finishingQueue = fq;
    processingQueue = new CarQueue();
    servicePool = rp;
  }
  public CarQueue getProcessingQueue() { return processingQueue; }
  public CarQueue getFinishingQueue() { return finishingQueue; }

  public Car car() { return car; }
  public void run() {
    try {
      while(!Thread.interrupted()) {
        car = waitingQueue.take();
        processingQueue.put(car);
        System.out.println("Rozpoczęto obsługę pojazdu o id: " + car.getId());
        servicePool.hire(CleanupService.class, this);
        servicePool.hire(WashService.class, this);
        servicePool.hire(WaxService.class, this);
      }
    } catch(InterruptedException e) {}

  }

  public synchronized boolean areAnyCarsInside() {
      return processingQueue.size() > 0 || waitingQueue.size() > 0;
  }

  public void showWaitingCarsAmount() {
      System.out.println("Pozostało: " + (processingQueue.size() + waitingQueue.size()) + " oczekujących aut.");
  }
}

class CarWashExit implements Runnable {
  private CarQueue carQueue;
  public CarWashExit(CarQueue cq) { carQueue = cq; }
  public void run() {
    System.out.println("Brama wyjazdowa zostaje otwarta.");
    try {
      while(!Thread.interrupted()) {
        Car c = carQueue.take();
        System.out.println("W bramie wyjazdowej jest pojazd" + c.getId());
        c.waitForAllServiceFinished();
        System.out.println(c);
      }
    } catch(InterruptedException e) {}
    System.out.println("Brama wyjazdowa zostaje zamknięta.");
  }
}

abstract class Service implements Runnable {
  private ServicePool pool;
  public Service(ServicePool p) { pool = p; }
  protected CarWashLine line;
  protected String serviceName;
  public Service assignLine(CarWashLine carWashLine) {
    this.line = carWashLine;
    return this;
  }
  private boolean inUse = false;
  public synchronized void use() {
    inUse = true;
    notifyAll();
  }

  abstract protected void performService();
  
  public void run() {
    System.out.println(this + " zostało otwarte.");
    try {
      powerDown();
      while(!Thread.interrupted()) {
        performService();
        powerDown();
      }
    } catch(InterruptedException e) {}
    System.out.println(this + " zostało zamknięte.");
  }
  private synchronized void
  powerDown() throws InterruptedException {
    inUse = false;
    line = null;
    pool.release(this);
    while(inUse == false)  // Power down
      wait();
  }
    @Override
    public synchronized String toString() {
        return "Stanowisko <" + serviceName + "> ";
    }
}

class CleanupService extends Service {
  public CleanupService(ServicePool pool) {
        super(pool);
        serviceName = "Sprzątające";
  }
  protected void performService() {
        try {
            Car car = line.car();
            if (car.needCleaning()) {
                car.cleaning();
                System.out.println(this + " sprzątanie pojazdu o id: " + car.getId() + " w toku...");
                TimeUnit.SECONDS.sleep(4);
                System.out.println(this + " sprzątanie pojazdu o id: " + car.getId() + " zakończone.");
                car.cleaned();
                if (! car.needWashing() && ! car.needWaxing()) {
                    line.getProcessingQueue().remove(car);
                    line.getFinishingQueue().put(car);
                }
            }
        } catch (InterruptedException ex) {
        }
  }
}

class WashService extends Service {
  public WashService(ServicePool pool) {
        super(pool);
        serviceName = "Myjące";
  }
  protected void performService() {
        try {
            Car car = line.car();
            if (car.needWashing()) {
                car.waitForWashing();
                car.washing();
                System.out.println(this + " mycie pojazdu o id: " + car.getId() + " w toku...");
                TimeUnit.SECONDS.sleep(1);
                System.out.println(this + " mycie pojazdu o id: " + car.getId() + " zakończone.");
                car.washed();
                if (! car.needWaxing()) {
                    line.getProcessingQueue().remove(car);
                    line.getFinishingQueue().put(car);
                }
            } 
        } catch (InterruptedException ex) {
        }
  }
}

class WaxService extends Service {
  public WaxService(ServicePool pool) {
        super(pool);
        serviceName = "Woskujące";
  }
  protected void performService() {
        try {
            Car car = line.car();
            if (car.needWaxing()) {
                car.waitForWaxing();
                car.waxing();
                System.out.println(this + " woskowanie pojazdu o id: " + car.getId() + " w toku...");
                TimeUnit.SECONDS.sleep(1);
                System.out.println(this + " woskowanie pojazdu o id: " + car.getId() + " zakończone.");
                car.waxed();
                line.getProcessingQueue().remove(car);
                line.getFinishingQueue().put(car);
            }
        } catch (InterruptedException ex) {
        }
  }
}

class ServicePool {
  private Set<Service> pool = new HashSet<Service>();
  public synchronized void add(Service s) {
    pool.add(s);
    notifyAll();
  }
  public synchronized void
  hire(Class<? extends Service> serviceType, CarWashLine line)
  throws InterruptedException {
    for(Service s : pool)
      if(s.getClass().equals(serviceType)) {
        pool.remove(s);
        s.assignLine(line);
        s.use(); 
        return;
      }
    wait();
    hire(serviceType, line); 
  }
  public synchronized void release(Service r) { add(r); }
}


class DateUtils {
  public static final String DATE_FORMAT_NOW = "HH:mm:ss";

  public static String now() {
    Calendar cal = Calendar.getInstance();
    SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
    return sdf.format(cal.getTime());

  }
}

public class CarWash {
  public static void main(String[] args) throws Exception {
    System.out.println(DateUtils.now().toString() + " rozpoczęcie pracy myjni...");
    CarQueue waitingQueue = new CarQueue(),
             finishingQueue = new CarQueue();
    ExecutorService exec = Executors.newCachedThreadPool();
    ServicePool servicePool = new ServicePool();
    CarWashEntrance entrance = new CarWashEntrance(waitingQueue);
    CarWashLine line = new CarWashLine(
      waitingQueue, finishingQueue, servicePool);
    exec.execute(new CleanupService(servicePool));
    exec.execute(new WashService(servicePool));
    exec.execute(new WaxService(servicePool));
    exec.execute(line);
    exec.execute(new CarWashExit(finishingQueue));
    exec.execute(entrance);
    TimeUnit.SECONDS.sleep(20);
    entrance.close();
    while (line.areAnyCarsInside()) {}
    exec.shutdownNow();
    System.out.println(DateUtils.now().toString() + " zakończenie pracy myjni.");
    line.showWaitingCarsAmount();
    System.exit(0);
  }
}

0

Problemy:

Nie wiem dlaczego pojazdy opuszczają myjnię dwukrotnie (często, klasa CarWashExit), no i nie wiem czemu zawiesza się to wszystko w pewnym miejscu. Wcześniej używałem wg TIJ CyclicBarrier ale to psuje całe założenie tego programu, sorry za multi posty, ale już nie myślę.

lipkerson
  • Rejestracja:ponad 17 lat
  • Ostatnio:ponad 2 lata
0

Super-pachnie baaardzo komercyjnym użyciem i wszystko by było Ok gdybyś ze swojej strony trochę włożył wysiłku. Masz IDE to masz debug...zaznaczaj znaczące operacje i patrz co isę dzieje krok po kroku....daj jakaś kontrole wyjątków (chociaż jak odpaliłem program to nie było błędów).
On nie jest zawieszony tylko czeka na synchronizację....rób break pointy i debug odpal...a tak w ogóle to jak jest 400linni kodu to po co go cały wklejasz-obcinaj trochę...ten kod da się w kilkunastu liniach dla fazy testów...debug debug debug


Another jam from the world for the jam from the voices of the world......
0

Dzięki za odpowiedź.

Komercyjne? To żadna komercja. To zadanie ze studiów jest, oparłem je na połączenie kilku programów z TIJ, gdzie przykłady są znakomite i może dlatego tak wygląda.

A kod cały wrzuciłem tylko dlatego żeby każdy mógł zobaczyć jak działa, jeśli będzie chciał.

W każdym razie zmieniłem trochę program i już prawie wszystko działa, ale mam problem z wykończeniem programu.

Program działa przez jakiś czas, po upływie danego czasu brama wjazdowa zostaje zamknięta. No ale jeśli w kolejkach do poszczególnych stacji są auta no to trzeba poczekać aż wszystkie wyjadą i wtedy wątki są zabijane i pokazywany jest komunikat że stanowisko zostało zamknięte (w przechwyceniu InterruptedException)

Samo sprawdzenie stanu kolejek działa, z tym że jeśli właśnie jest obsługiwany jakiś pojazd, może dojść do sytuacji, że w kolejce już nic nie ma i zostanie pokazany komunikat:

Stanowisko X rozpoczęło mycie pojazdu Y
Stanowisko X zostało zamknięte.

A więc tak jakby pojazd będzie myty na zawsze, chciałem to zmienić więc dodałem jeszcze jedną flagę

inUse. Kod klasy bazowej dla stanowisk poniżej:

Kopiuj
public abstract class Station implements Runnable {
    protected LinkedBlockingQueue<Vehicle> vehicles
            = new LinkedBlockingQueue<Vehicle>();

    protected MyDialog view;

    protected MyDialog exit;

    private boolean inUse = false;

    public synchronized void setStatus(boolean status) {
            this.inUse = status;
    }

    public synchronized boolean isInUse() {
        return this.inUse;
    }

    public Station(MyDialog panel, MyDialog exit) {
        this.view = panel;
        this.exit = exit;
    }

    public synchronized void addVehicle(Vehicle v) {
        if (this.vehicles.size() < 15) {
            this.vehicles.add(v);
        }
        else {
            this.view.append("W kolejce czeka 15 samochodów, nie ma więcej miejsc.");
            this.exit.append(v + " opuszcza myjnię.");
        }
    }

    public synchronized boolean areAnyCarsAwaits() {
        return this.vehicles.size() > 0 || this.isInUse();
    }

    public void run()  {
        this.view.append("Stanowisko zostało otwarte.");
        try {
            while(! Thread.interrupted()) {
                this.setStatus(true);
                this.serve();
                this.setStatus(false);
            }
        } catch(InterruptedException ex)  {
             this.view.append("Stanowisko zostało zamknięte.");
        }

    }
    protected abstract void serve() throws InterruptedException;
}

Metodą areAnyCarsAwaits() sprawdzam czy można bezpiecznie zamknąć stanowisko, jednak do tego nie dochodzi. Gdy kolejka jest pusta debug pokazuje ze inUse jest zawsze true, więc wątek nigdy nie zostaje zabity, a ja nie otrzymuje na wyjście komunikatu "Stanowisko zostało zamknięte."

Przykładowa implementacja metody serve() wygląda tak, ale chyba to nie ma w tym nic do gadania:

Kopiuj
    protected void serve() throws InterruptedException {
        Vehicle v = this.vehicles.take();
        this.view.append("Sprzątanie " + v + " w toku...");
        TimeUnit.SECONDS.sleep(3);
        this.view.append("Sprzątanie " + v + " zostało zakończone.");
        v.doCleaning();
        if (v.washed() && v.cleaned() && v.polished())  {
            this.exit.append(v + " opuszcza myjnię...");
        }
    }

Doradzi ktoś?

Pozdrawiam

Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)