Еднопосочен мост с коли идващи от двете посоки с графичен интерфейс и ограничение на максимален брой коли последователно в една посока

За реализация на графичния интерфейс в класа на моста е въведен вътрешен клас - Gui. Той наследява класа фрейм и съдържа 5 панела:

Всяка кола се задава върху съответния панел с бутон  с етикет буквата V и поредния номер на колата. Бутонът е зелен, ако се движи отляво надясно и жълт - в противоположната посока. За да могат да бъдат премахвани бутоните при напускане на съответния панел се поддържат три ArraiList<Vehicle>  за референциите на бутоните в първите три панела. Намирането на бутона става в цикъл по етикета му.

Панелът за моста е оцветен в сиво, когато мостът е отворен за преминаване и в розово - когато е затворен.

Мост - ресурс за ползване от колите. 

import java.awt.Color;
import java.util.ArrayList;
import javax.swing.*;

public class Bridge {
    private int nVh,cnt_cons, max_cons;
    private boolean closed;
    private Gui gui;
    Bridge(int max_cons){
        nVh = cnt_cons=0;
        closed = false;
        this.max_cons=max_cons;
        gui = new Gui();
    }
    ////////  for GUI  ----------------------------------
    public class Gui extends JFrame{
        int w=800,h=400;
        ArrayList<JButton> a_l=new ArrayList<JButton>();
        ArrayList<JButton> a_r=new ArrayList<JButton>();
        ArrayList<JButton> on=new ArrayList<JButton>();
        JPanel  pa_l= new JPanel(),
                pa_r= new JPanel(),
                pon= new JPanel(),
                pp_l= new JPanel(),
                pp_r= new JPanel();

        Gui() {
            setBounds(50, 50, w, h);
            setLayout(null);

            pa_l.setBounds(10, 10, w/3, h/3);
            add(pa_l);

            pp_l.setBounds(10, h/3+50, w/3, h/2);
            add( pp_l);

            pon.setBackground(Color.LIGHT_GRAY);
            pon.setBounds(w/3+20, h/4, w/3-20, h/4);
            add(pon);

            pa_r.setBounds(2*w/3, 10, w/3, h/3);
            add(pa_r);

            pp_r.setBounds(2*w/3, h/3+50, w/3, h/2);
            add(pp_r);

            setDefaultCloseOperation(EXIT_ON_CLOSE);
            setVisible(true);
        }
    }

    synchronized public void addGV(Vehicle v){  //gui new Vehicle
        JButton bt=new JButton(v.name);
        if(v.lr) {
            gui.pa_l.add(bt);
            bt.setBackground(Color.green);
            gui.pa_l.revalidate();
            gui.pa_l.repaint();
            gui.a_l.add(bt);
        }
        else {
            gui.pa_r.add(bt);
            bt.setBackground(Color.yellow);
            gui.pa_r.revalidate();
            gui.pa_r.repaint();
            gui.a_r.add(bt);
        }
    }
    synchronized public void onBGV(Vehicle v){  //gui on the bridge
        if(v.lr) {
            for(JButton b:gui.a_l){                
                if(b.getText().equals(v.name)) {
                    gui.pa_l.remove(b);  // remove from panel
                    gui.pon.add(b);         // put in the on panel
                    gui.on.add(b);          // and on the list
                    gui.pon.revalidate();
                    gui.pa_l.repaint();
                    gui.pa_l.revalidate();
                    gui.pon.repaint();
                    gui.a_l.remove(b);
                    break;
                }
            }       
        }
        else {
            for(JButton b:gui.a_r) { 
                if(b.getText().equals(v.name)) {
                    gui.pa_r.remove(b);  // remove from panel
                    gui.pon.add(b);         // put in the on
                    gui.on.add(b);          // and on the list
                    gui.pon.revalidate();
                    gui.pon.repaint();
                    gui.pa_r.revalidate();
                    gui.pa_r.repaint();
                    gui.a_l.remove(b);  // remove from list
                    break;
                }
            } 
        }        
    }

    synchronized public void lvBGV(Vehicle v){  //gui leave the bridge
        for(JButton b:gui.on) { 
            if(b.getText().equals(v.name)) {
                gui.pon.remove(b);  // remove from panel
                gui.pon.revalidate();
                gui.pon.repaint();
                if(v.lr) {
                    gui.pp_r.add(b);         // put in the on
                    gui.pp_r.revalidate();
                    gui.pp_r.repaint();
                }
                else {
                    gui.pp_l.add(b);         // put in the on
                    gui.pp_l.revalidate();
                    gui.pp_l.repaint();
                }                
                break;
            }
        }       
    }
    synchronized public void closeB() {
        gui.pon.setBackground(Color.PINK);
        gui.pon.revalidate();
        gui.pon.repaint();
    }
    synchronized public void openB() {
        gui.pon.setBackground(Color.LIGHT_GRAY);
        gui.pon.revalidate();
        gui.pon.repaint();
    }

    ///////// Gui  ---------------------------------------------

    synchronized public int brN(){
        return nVh;
    }
    synchronized public void takeB(boolean lr ){
        while((nVh>0)&& (lr==true)||
                (nVh<0) && (lr==false)||closed){
            System.out.println("\t"+Thread.currentThread().getName()+" waiting");
            try{     wait();   }
            catch(InterruptedException e){
                System.err.println(e);
            }
        }
        try {
            Thread.sleep(1000);
        }
        catch(InterruptedException ie) {}
        if (lr) nVh--;
        else nVh++;
        System.out.println(Thread.currentThread().getName()+" on the bridge");
        onBGV((Vehicle)(Thread.currentThread()));
        cnt_cons++;
        if(cnt_cons>=max_cons) {
            closed =true;
            closeB();
        }
        if(closed)System.out.println("The bridge is closed");
    }
    synchronized public void leaveB(boolean lr ){
        if (nVh>0) nVh--;
        else nVh++;
        System.out.println("\t\t"+Thread.currentThread().getName()+" leave the bridge");
        lvBGV((Vehicle)Thread.currentThread());
        if(nVh==0) {
            cnt_cons=0;
            closed = false;
            openB();
            System.out.println("The bridge is open");
        }
        notifyAll();
    }
}

Коли - нишки,

public class Vehicle extends Thread{
    boolean lr;
    Bridge b;
    String name;
    static int num;
    Vehicle(boolean lr, Bridge b){
        this.lr=lr;
        this.b = b;
        name = "V "+ ++num;
        b.addGV(this);
        super.setName(name);   
    }
    public void run(){
        b.takeB(lr);
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e){}
        b.leaveB(lr);
    }
    public String toString() {
        return name;
    }
}

Самият модел:

public class Circ {
    static Bridge b = new Bridge(3);
    public static void main(String arg[]){    
        for(int i = 0; i < 20; i++){
            Vehicle v =new Vehicle(Math.random()>0.5?true:false, b);         
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException ex) {}
            v.start();
        } 
    }
}