Thread Synchronization in Java (synchronize collections)

6

I have set a Thread in Java in which I want to simulate airplanes arriving and departing from the airport, class Aviao contains only number and 10 passengers

public class Aviao  {
    //numero de Aviao
    private int numeroAviao;
    //contém uma lista de passageiros
    private List<Passageiro> passageiros;

   public Aviao(int numero, int tamanho) {
            this.numeroAviao = numero;
            this.passageiros = new ArrayList<>(tamanho);
    }

    @Override
    public void adicionaPassageiro(Passageiro p) {
            this.passageiros.add(p);
    }
}

The class Aeroporto :

public class Aeroporto {
    private List<Passageiro> passageirosNoAeroporto;
    private List<Aviao> avioes;
    private Map<Aviao, ThreadAviao> threadAviao;
    private final Object mutex;
    private boolean comecou;
    private final Relogio relogio;

public Aeroporto(int qtAviao) {
        this.mutex = new Object();
        this.comecou = false;
        this.passageirosNoAeroporto = new ArrayList<>();
        this.avioes = Collections.synchronizedList(new ArrayList<>());
        this.relogio = new Relogio();
        this.threadAviao = new HashMap<>();
        for (int j = 0; j < qtAviao; j++) {
            Aviao aviao = new Aviao(j + 1, 10);
            this.threadAviao.put(aviao, new ThreadAviao(this, aviao));
     }
}

Add airplane method to the airport:

public synchronized void AviaoChegou(Aviao aviao) throws InterruptedException {
        //adicionar aviao no aeroporto
        this.avioes.add(aviao);
        //usar uma lista sincronizada
        List list = Collections.synchronizedList(avioes);
        synchronized (list) {
            //iterar lista de avioes
            Iterator i = list.iterator();
            while (i.hasNext()) {
                aviao = (Aviao) i.next();
                // iterar a lista de passageiros
                Iterator<Passageiro> it = aviao.getPassageiros().iterator();
                  while (it.hasNext()) {
                     Passageiro p = it.next();
                     //adicionar os pasageiros no aeroporto
                     passageirosNoAeroporto.add(p);
                     //remove os passageiros do aviao
                     it.remove();
                }
            }
        }
    }

Aircraft method to leave when empty

 public synchronized void AviaoPartiu(Aviao aviao) {
      //usar uma lista sincronizada
            List<Aviao> lista = Collections.synchronizedList(avioes);
            synchronized (lista) {
              //iterar a lista de avioes
                Iterator<aviao> i = lista.iterator();
                while (i.hasNext()) {
                    aviao = (Aviao) i.next();
                   //remove o aviao do aeroporto -> e da thread Aviao e Dá erro
                   //(Exception in thread 
                   //"Thread-2" java.util.ConcurrentModificationException)
                    this.avioes.remove(aviao); //usar isto ou não?
                   //remove o aviao do aeroporto -> e não da thread Aviao?
                   i.remove();//usar isto o aviao 
                  //faz a simulação outra vez até morrer
                }
            }
        }

Then I have the class ThreadAviao

public class ThreadAviao extends Thread {

        private final Aviao aviao;
        private final Aeroporto aeroporto;

        public ThreadAviao(Aeroporto aeroporto, Aviao aviao) {
            this.aviao = aviao;
            this.aeroporto = aeroporto;
        }

        @Override
        public void run() {
            try {
                synchronized (mutex) {
                    while (!comecou) {
                        mutex.wait();
                    }
                List<Aviao> lista = new ArrayList<>();
                //adiciona o aviao a lista
                lista.add(aviao);
                //ordena os avioes
                Collections.sort(lista);
                //escolhe um aviao 
                for (Aviao av : lista) {
                    //inicia a etapa
                    etapaAviao.executar(aeroporto, av);
                }
               }
            } catch (InterruptedException e) {
                // Não faz nada.
            }
        }
    }

My question is that when I have 2 airplanes created instead of each one does their process, and when one leaves and is removed from the list of airplanes at the airport gives error as shown in the image below

AndmygoalistotrytosynchronizeThreadsoyoucanachievethegoalasshowninthefigurebelow?

  

I think the problem is that you are not deleting the airplane from   airport when you left for another country

Any suggestions?

    
asked by anonymous 28.11.2015 / 23:52

1 answer

0

I already managed to get it to work as expected, here's the solution

class Aviao contains only number and 10 passengers

public class Aviao implements Comparable<Aviao>  {
    //numero de Aviao
    private int numeroAviao;
    //contém uma lista de passageiros
    private List<Passageiro> passageiros;

   public Aviao(int numero, int tamanho) {
            this.numeroAviao = numero;
            this.passageiros = new ArrayList<>(tamanho);
    }

    public void adicionaPassageiro(Passageiro p) {
            this.passageiros.add(p);
    }

    public List<Passageiro> getPassageiros() {
            return this.passageiros;
    }

   public int getNumeroAviao() {
           return this.numeroAviao;
    }

   public int compareTo(Aviao novoAviao) {
            return this.numeroAviao - novoAviao.getNumeroAviao();
    }
}

The class Aeroporto :

public class Aeroporto {
    private List<Passageiro> passageirosNoAeroporto;
    private List<Aviao> avioes;
    private Map<Aviao, ThreadAviao> threadAviao;
    private final Object mutex;
    private boolean comecou;
    private final Relogio relogio;

public Aeroporto(int qtAviao) {
        this.mutex = new Object();
        this.comecou = false;
        this.passageirosNoAeroporto = new ArrayList<>();
        this.avioes = new ArrayList<>();
        this.relogio = new Relogio();
        this.threadAviao = new HashMap<>();
        for (int j = 0; j < qtAviao; j++) {
            Aviao aviao = new Aviao(j + 1, 10);
            this.threadAviao.put(aviao, new ThreadAviao(this, aviao));
     }
}

Add airplane method to the airport:

public synchronized void AviaoChegou(Aviao aviao) throws InterruptedException {
        //adicionar aviao no aeroporto
        this.avioes.add(aviao);
        //usar uma lista sincronizada
        List<Aviao> lista = Collections.synchronizedList(avioes);
        synchronized (lista) {
            //iterar lista de avioes
            Iterator<Aviao> i = lista.iterator();
            while (i.hasNext()) {
                  // o aviao que chegou é igual ao aviao iterado
                  aviao = (Aviao) i.next();
                // iterar a lista de passageiros
                Iterator<Passageiro> it = aviao.getPassageiros().iterator();
                  while (it.hasNext()) {
                     Passageiro p = it.next();
                     //adicionar os pasageiros no aeroporto
                     passageirosNoAeroporto.add(p);
                     //remove os passageiros do aviao
                     it.remove();
                }
            }
        }
      }

Aircraft method to leave when empty

 public synchronized void AviaoPartiu(Aviao aviao) {
      //usar uma lista sincronizada
            List<Aviao> lista = Collections.synchronizedList(avioes);
            synchronized (lista) {
              //iterar a lista de avioes
                Iterator<aviao> i = lista.iterator();
                while (i.hasNext()) {
                  //aviao que vai partir é igual ao aviao iterado
                  aviao = (Aviao) i.next();
                   //remove o aviao do aeroporto
                   i.remove();
            }
          }
        }

Then I have the class ThreadAviao

    public class ThreadAviao extends Thread {

            private final Aviao aviao;
            private final Aeroporto aeroporto;

            public ThreadAviao(Aeroporto aeroporto, Aviao aviao) {
                this.aviao = aviao;
                this.aeroporto = aeroporto;
            }

            @Override
            public void run() {
                try {
                    synchronized (mutex) {
                        while (!comecou) {
                            mutex.wait();
                        }
                   //usar uma lista sincronizada
                    List<Aviao> lista = Collections.synchronizedList(new ArrayList<>());
                    //adiciona o aviao a lista
                    lista.add(this.aviao);
                    //escolhe um aviao 
                    synchronized (lista) {
                    for (Aviao novoAviao : lista) {
                    System.out.println(" Aviao " + novoAviao.numeroAviao());
                      //inicia a etapa
                      etapaAviao.executar(this.aeroporto, novoAviao);
                        }
                    }
                } catch (InterruptedException e) {
                    // Não faz nada.
                }
            }
        }

method that performs airplane stage

public void executar(Aeroporto aeroporto, Aviao aviao) {
         //contador
         int contador = 0;
        //por enquanto a cada aviao executar uma 
        //etapa sai de executa a etapa de outro aviao
        while (contador != 1) {
            aeroporto.AviaoChegou(aviao);
            //aguardar um tempo
            aeroporto.getRelogio().esperar();
            //aviao partiu
            aeroporto.AviaoPartiu(aviao);
            //incrementa contador
            contador++;
        }
    }

Here is the simulation figure

    
02.12.2015 / 23:37