04.06.2008 | 22:12:22
immagine
Ing. Emanuele Scapin

Java, es6, gestione thread navi e condivisione della risorsa porto.
  • Si creino delle classi in JAVA per simulare la seguente problematica.

    Si pensi ai tipici porti delle isole greche dove sono presenti un numero limitato di moli per gestire l’attracco delle navi.

    Ogni nave è caratterizzata da:
    a) un nome;
    b) una dimensione (larghezza, lunghezza);
    c) un tonnellaggio;
    d) tipo nave (passeggeri, traghetto, merci, container, cisterna, ecc..);
    e) numero massimo passeggeri (se nave passeggeri);
    f) numero massimo autovetture (se nave traghetto);

    Il porto può gestire le navi sui moli con queste regole:
    a) gestisce chi ha priorità più elevata, ovvero le navi passeggeri e/o i traghetti;
    b) ogni molo gestisce una sola nave alla volta purché di dimensioni compatibili.

    Ogni molo del porto è caratterizzato da una dimensione (lunghezza e larghezza) che deve essere compatibile con la dimensione della nave che vuole attraccare; le navi che hanno dimensioni incompatibili con tutti i moli del porto non possono attraccare.
    Ogni nave rimane attraccata al molo assegnato per un tempo caratteristico per la nave stessa; le navi passeggeri e le navi traghetto resteranno ferme al molo a seconda del numero passeggeri o del numero di autovetture da imbarcare o sbarcare.

     

  • Enumerativo per la definizione del tipo di nave.

                public enum TipoNave {
                    passeggeri, traghetto, merci, container, cisterna;
                }
            
  • Classe per la gestione dei dati di un molo.
    Con due metodi per gestire l'occupazione del molo da parte di una nave e successivamente il suo rilascio.

                public class Molo {
                    private int numero;
                    private int lunghezza;
                    private int larghezza;
                    private boolean occupato = false;
    
                    public Molo(int numero, int lunghezza, int larghezza) {
                        this.numero = numero;
                        this.lunghezza = lunghezza;
                        this.larghezza = larghezza;
                    }
    
                    public int getNumero() {
                        return numero;
                    }
    
                    public int getLunghezza() {
                        return lunghezza;
                    }
    
                    public int getLarghezza() {
                        return larghezza;
                    }
    
                    public boolean isOccupato() {
                        return occupato;
                    }
    
                    public void pushNave(Nave nave) {
                        // occupa il molo
                        nave.setMoloassegnato(this.numero);
                        this.occupato = true;
                    }
    
                    public void popNave(Nave nave) {
                        // abbandona il molo
                        nave.setMoloassegnato(0);
                        this.occupato = false;
                    }
    
                } 
            
  • Il porto è la risorsa condivisa dalle navi, contiene un elenco di moli.
    Sono implementati dei metodi gestiti dal monitor (metodi sincronizzati) che permettono a ogni nave di poter gestire i dati condivisi in sicurezza.

                public class Porto {
                    private String nome;
    
                    private ArrayList<Molo> moli = new ArrayList<Molo>();  
    
                    public Porto(String nome) {
                        this.nome = nome;
                    }
    
                    public String getNome() {
                        return nome;
                    }
    
                    public void aggiungiMolo(Molo molo) {
                        if (molo != null) {
                            moli.add(molo);
                        }
                    }
    
                    public int numeroMoli() {
                        return moli.size();
                    }
    
                    public ArrayList<Molo> elencoMoli() {
                        return moli;
                    }
    
                    public Molo datiMolo(int i) {
                        Molo ret = null;
                        if (i >= 0 && i < moli.size()) {
                            ret = moli.get(i);
                        }
                        return ret;    
                    }
    
                    public synchronized int numeroMoliLiberi() {
                        int ret = 0;
                        for(int i=0; i<moli.size(); i++) {
                            if (!moli.get(i).isOccupato()) ret++;
                        }
                        return ret;
                    }
    
                    private synchronized int verificaMolo(Nave nave) {
                        int ret = 0;
    
                        // scansione dei moli liberi per verificare se ce n'è uno che sia
                        // adeguato alle dimensioni della nave richiedente
                        int i=0;
                        //for(int i=0; i<moli.size(); i++) {
                        while (i<moli.size() && ret==0) {
                            if (!moli.get(i).isOccupato()) {
                                if ((nave.getLarghezza() < moli.get(i).getLarghezza()) &&
                                    (nave.getLunghezza() < moli.get(i).getLunghezza())) {
                                    // il molo è adeguato, la nave quindi può occupare il molo
                                    moli.get(i).pushNave(nave);
                                    System.out.println("la nave " + nave.getNome() + 
                                            " ha occupato il molo numero " + 
                                            moli.get(i).getNumero());
                                    ret = 1;
                                    //break;
                                }
                            }
                            i++;
                        }
    
                        return ret;
                    }
    
                    public synchronized int occupaMolo(Nave nave) {
                        int ret = 0;
    
                        try {
                           // controlla se ci sono moli liberi 
                           if (numeroMoliLiberi() > 0) {
                               // contralla se un molo libero è utilizzabile dalla nave
                              if (verificaMolo(nave) > 0) {
                                  // può acquisisre il molo libero in quanto le dimensioni sono
                                  // adeguate
                                  ret = 1;
                              }
                              else {
                                  wait();
                              }
                           }
                           else {
                               wait();
                           }
                        }
                        catch(Exception ex) {
                            ret = 0;
                        }
    
                        return ret;
                    }
    
                    public synchronized void rilasciaMolo(Nave nave) {
                        // nave rilascia il molo
                        int numeromolo = nave.getMoloassegnato();
                        if (numeromolo > 0) {
                          // nave lascia molo, la numerazione dei moli parte da 1 (uno), mentre 
                          // nella lista la numerazione parte da 0 (zero)
                          moli.get(numeromolo-1).popNave(nave);
                          System.out.println("la nave " + nave.getNome() + 
                                  " ha lasciato il molo numero " + 
                                  moli.get(numeromolo-1).getNumero());
                          // notifica per risveglio thread (navi) in attesa
                          notifyAll();
                        }
                    }
                }
            
  • La classe Nave è il thread che condivide il porto, ogni thread concorre con gli altri nell'utilizzo del porto e dei suoi moli.

    public class Nave extends Thread {
        private String nome;
        private int larghezza;
        private int lunghezza;
        private float tonnellaggio;
        private int nmumeroPasseggeri = 0;
        private int numeroAuto = 0;
        // per il tipo nave è stato usato un enumerativo anziché un intero
        private TipoNave tipoNave;
        // tipo nave con valore intero
        // private int tipoNave = -1; // 0=passeggeri, 1=traghetto, 2= merci, 
        // 3=container, 4=cisterna;
        private Porto porto; // il porto è la risorsa condivisa
        
        private int moloassegnato = 0;
    
        public Nave(String nome, int lunghezza, int larghezza, float tonnellaggio, 
                TipoNave tipoNave, Porto porto) {
            this.nome = nome;
            this.larghezza = larghezza;
            this.lunghezza = lunghezza;
            this.tonnellaggio = tonnellaggio;
            this.tipoNave = tipoNave;
            this.porto = porto;
            if (tipoNave == TipoNave.passeggeri || tipoNave == TipoNave.traghetto) {
                this.setPriority(Thread.MAX_PRIORITY);
            }
            else {
                this.setPriority(Thread.NORM_PRIORITY);
            }
        }
    
        public String getNome() {
            return nome;
        }
    
        public int getLarghezza() {
            return larghezza;
        }
    
        public int getLunghezza() {
            return lunghezza;
        }
    
        public float getTonnellaggio() {
            return tonnellaggio;
        }
    
        public int getNmumeroPasseggeri() {
            return nmumeroPasseggeri;
        }
    
        public int getNumeroAuto() {
            return numeroAuto;
        }
    
        public void setNmumeroPasseggeri(int nmumeroPasseggeri) {
            this.nmumeroPasseggeri = nmumeroPasseggeri;
        }
    
        public void setNumeroAuto(int numeroAuto) {
            this.numeroAuto = numeroAuto;
        }
    
        public TipoNave getTipoNave() {
            return tipoNave;
        }
    
        public int getMoloassegnato() {
            return moloassegnato;
        }
    
        public void setMoloassegnato(int moloassegnato) {
            this.moloassegnato = moloassegnato;
        }
        
        @Override
        public void run() {
            while(true) {
                try {
                    if (porto.occupaMolo(this) == 1) {
                        if (tipoNave == TipoNave.traghetto) 
                            Thread.sleep(numeroAuto * 10);
                        else if (tipoNave == TipoNave.passeggeri) 
                            Thread.sleep(nmumeroPasseggeri * 10);
                        else 
                            Thread.sleep(5000);
                        
                        porto.rilasciaMolo(this);
                        
                        // attesa prima di ritornare in porto un'altra volta
                        Thread.sleep(Math.round(3000)*10);
                    }  
                    else {
                        System.out.println("la nave " + this.nome + 
                                " non ha un molo disponibile");
                    }
                }
                catch(Exception ex) {
                    System.out.println("errore run " + ex.getMessage());
                }
            }
        }
    }
            

© Emanuele Scapin 2009-2016

 

Valid HTML 4.01! Valid CSS!