Java Thread Synchronization (synchronize collections)

Asked

Viewed 1,243 times

6

I have defined a Thread in Java where I intend to simulate planes arriving and departing from the airport, the 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));
     }
}

Method add plane at 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();
                }
            }
        }
    }

Method for aeroplane 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
                }
            }
        }

and 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 doubt is that when I have 2 planes created instead of each one does its process, and when one leaves and is removed from the list of planes at the airport gives error as shown in the image below

and my goal is to try to synchronize the Thread to achieve the objective as shown in the figure below?

I think the real problem is that you’re not excluding the plane from the airport when it left for another country

Any suggestions?

  • the Aviaopartiu method you are removing all aircraft?

  • @Skywalker, I’m just removing the plane that arrived, I changed the flight path departed, the plane that’s leaving will be equal to the plane iterated from the list and erased through the operation this.avioes.remove(aviao); and then the thread of the other plane runs but only error after

  • @Skywalker, if in the airplane methodParty I’m removing all the planes, I think the other thread would not perform as shown in figure 1

  • So I hadn’t seen that comparison if, try giving break; after removing. This should resolve.

  • I don’t know if that’s necessary i.remove();

  • @Skywalker, I tried giving break; after removing the plane in this.avioes.remove(aviao); and gave no error but did not solve and continued to perform the stage of the same plane that just left

  • Ai is already a problem of logic. Logo vo da mais uma parsed in your code.

  • @Skywalker, thank you

  • @Skywalker, I think I’ve solved the bug problem and instead of using the this.avioes.remove(aviao); the best is to use i.remove(); when we are using the iterator to delete an object in a list, if, it was necessary to make aviao = (Aviao) i.next(); and then in the execution of the step and create a contador to control the step of each thread that will be executed only once and worked out as shown in the figure above, just need to sort and since it solves my doubt the solution is was edited in the code that had already been placed before.

  • Hello Renata, welcome to [en.so]. I saw that solved your problem, cool! But the solution should be the answer, because here we operate a little different from the forums. Could you separate the question from the answer in different publications? Enjoy and make a [tour] to know a little better the functioning of our community.

  • @Math, thanks for the guidance

Show 6 more comments

1 answer

0


I’ve been able to make it work as expected, here’s the solution

the 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));
     }
}

Method add plane at 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();
                }
            }
        }
      }

Method for aeroplane 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();
            }
          }
        }

and 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 performing the aviary step

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 picture of the simulation inserir a descrição da imagem aqui

Browser other questions tagged

You are not signed in. Login or sign up in order to post.