Auf Thema antworten

Wie es richtig geht... schwierig. Ich würde es mal so skizzieren (eine Richtung):

[code=Java]

import java.util.*;

import java.util.concurrent.*;

import java.util.concurrent.locks.*;


public class Rail {


    public static class Track {

        final Lock lock = new ReentrantLock(true);

        final Condition greenLights = lock.newCondition();

        final Condition left = lock.newCondition();


        Queue<Train> trains = new ConcurrentLinkedQueue<>();

        Queue<Train> queue = new ConcurrentLinkedQueue<>();

               


        public void occupy(Train train) throws InterruptedException {

            queue.add(train);                 // Reihe den Zug erstmal ein

            lock.lock();                      // Sperre ab hier

            try {

                while (trains.size() >= 3) {  // wenn bereits drei Züge auf dem Gleis

                    greenLights.await();      // warte auf eine grüne Ampel

                }

                trains.add(queue.remove());   // schiebe den nächsten Zug aufs Gleis

            } finally {

                lock.unlock();                // Sperre in jedem Fall aufheben

            }

        }


        public void leave(Train train) throws InterruptedException {

            lock.lock();                      // Sperre ab hier

            try {

                while (trains.peek() != train) {

                    left.await();

                }

                Train t = trains.remove();    // nimm den nächsten Zug vom Gleis

                greenLights.signal();         // und schalte die Ampel auf "grün"

                left.signal();

            } finally {

                lock.unlock();                // Sperre in jedem Fall aufheben

            }

        }

    }

   

    public static class Train extends Thread {

        private final Track track;

        private final int delay;


        public Train(Track track, int delay) {

            this.track = track;

            this.delay = delay;

        }


        public void run() {

            try {

                System.out.println(getName() + " -> einfahren");

                track.occupy(this);

                System.out.println(getName() + " -> warte " + delay + " ms");

                Thread.sleep(delay);

                System.out.println(getName() + " -> verlässt Gleis");

                track.leave(this);

                System.out.println(getName() + " -> hat Gleis verlassen");

            } catch (InterruptedException ex) {

                ex.printStackTrace();

            }

        }

    }


    public static void main(String[] args) {

        Track track = new Track();

        for (int i = 0; i < 10; i++) {

            new Train(track, (int)(Math.random() * 3000)).start();

        }           

    }

}[/code]



Oben