Navigation

    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Popular
    • Users
    • Groups

    ConcurrentModificationException

    Sans suite
    1.10.x
    5
    15
    3041
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • Ama
      Ama last edited by

      Nouveau problème suite à la résolution de mon précédent problème,

      Je me cogne une belle erreur du type ConcurrentModificationException j’ai testé les possibles méthodes pour résoudre ce problème en vain :’(

      :::

      package lib.craftstudio.common.animation;
      
      import java.util.ArrayList;
      
      import lib.craftstudio.common.IEntityAnimated;
      import net.minecraft.entity.Entity;
      import net.minecraftforge.common.MinecraftForge;
      import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
      import net.minecraftforge.fml.common.gameevent.TickEvent;
      import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
      import net.minecraftforge.fml.relauncher.Side;
      import net.minecraftforge.fml.relauncher.SideOnly;
      
      public class AnimTickHandler
      {
          private ArrayList <ientityanimated>activeEntities    = new ArrayList<ientityanimated>();
          private ArrayList <ientityanimated>removableEntities = new ArrayList<ientityanimated>();
      
          public AnimTickHandler()
          {
              MinecraftForge.EVENT_BUS.register(this);
          }
      
          public void addEntity(IEntityAnimated entity)
          {
              this.activeEntities.add(entity);
          }
      
          // Called when the client ticks.
          @SubscribeEvent
          @SideOnly(Side.CLIENT)
          public void onClientTick(TickEvent.ClientTickEvent event)
          {
              if (!this.activeEntities.isEmpty())
                  if (event.phase == Phase.START)
                  {
                      for (IEntityAnimated entity : this.activeEntities)
                      {
                          entity.getAnimationHandler().animationsUpdate();
      
                          if (((Entity) entity).isDead)
                              this.removableEntities.add(entity);
                      }
      
                      for (IEntityAnimated entity : this.removableEntities)
                          this.activeEntities.remove(entity);
                      this.removableEntities.clear();
                  }
          }
      
          // Called when the server ticks. Usually 20 ticks a second.
          @SubscribeEvent
          @SideOnly(Side.SERVER)
          public void onServerTick(TickEvent.ServerTickEvent event)
          {
              if (!this.activeEntities.isEmpty())
                  if (event.phase == Phase.START)
                  {
                      for (IEntityAnimated entity : this.activeEntities)
                      {
                          entity.getAnimationHandler().animationsUpdate();
      
                          if (((Entity) entity).isDead)
                              this.removableEntities.add(entity);
                      }
      
                      for (IEntityAnimated entity : this.removableEntities)
                          this.activeEntities.remove(entity);
                      this.removableEntities.clear();
                  }
          }
      
          // Called when a new frame is displayed (See fps)
          @SubscribeEvent
          @SideOnly(Side.CLIENT)
          public void onRenderTick(TickEvent.RenderTickEvent event)
          {}
      
          // Called when the world ticks
          @SubscribeEvent
          public void onWorldTick(TickEvent.WorldTickEvent event)
          {}
      }
      

      :::

      Lien des logs: https://gist.githubusercontent.com/ZeAmateis/c7430a6353cf758d599901ff0c2d44d6/raw/7a6e2b0788c2ad0cefdb614e32d0f2533b65a4d2/eclipse.logs

      Merci à toute les personnes m’aidant à corriger ce problème !

      PS: N’utilisez pas cette classe pour n’importe quelle raison, elle fait partie de l’api d’animation de CraftStudio elle n’est donc pas censée se retrouver dans la nature, AMOUR SUR VOUS MERCI  ❤</ientityanimated></ientityanimated></ientityanimated></ientityanimated>

      1 Reply Last reply Reply Quote 0
      • SCAREX
        SCAREX last edited by

        Essaye d’utiliser un vector au lieu d’une ArrayList

        1 Reply Last reply Reply Quote 0
        • Ama
          Ama last edited by

          Même problème qu’une array 😕

          1 Reply Last reply Reply Quote 0
          • RedRelay
            RedRelay Moddeurs confirmés last edited by

            Surtout pas ! Vector est une classe obsolète qui n’est la que pour répondre aux contraintes de la rétrocompatibilité !

            Tu utilise un iterator implicite dans tes boucles, vérifie que tu ne modifie pas ta liste lorsqu’elle est parcourue par un iterator de ce type.
            ArrayList n’est pas thread-safe. Vu les opérations que tu réalises sur tes listes, une ArrayList semble être une aberration.
            L’ArrayList est efficace pour les accès direct (via des indices) et est très gourmande en ressource lorsqu’il s’agit de faire des ajouts/suppressions.
            Vu que tu accès aux éléments via un itérator, utilise plutôt une LinkedList.
            Si tu dois faire des modifications, utilise Iterator.remove().

            1 Reply Last reply Reply Quote 0
            • Ama
              Ama last edited by

              Donc même avec la linkedList il y a la même erreur classe actuelle:

              :::

              package lib.craftstudio.common.animation;
              
              import java.util.LinkedList;
              
              import lib.craftstudio.common.IEntityAnimated;
              import net.minecraft.entity.Entity;
              import net.minecraftforge.common.MinecraftForge;
              import net.minecraftforge.fml.common.eventhandler.SubscribeEvent;
              import net.minecraftforge.fml.common.gameevent.TickEvent;
              import net.minecraftforge.fml.common.gameevent.TickEvent.Phase;
              import net.minecraftforge.fml.relauncher.Side;
              import net.minecraftforge.fml.relauncher.SideOnly;
              
              public class AnimTickHandler
              {
                 private LinkedList <ientityanimated>activeEntities    = new LinkedList<ientityanimated>();
                 private LinkedList <ientityanimated>removableEntities = new LinkedList<ientityanimated>();
              
                 public AnimTickHandler()
                 {
                     MinecraftForge.EVENT_BUS.register(this);
                 }
              
                 public void addEntity(IEntityAnimated entity)
                 {
                     this.activeEntities.add(entity);
                 }
              
                 // Called when the client ticks.
                 @SubscribeEvent
                 @SideOnly(Side.CLIENT)
                 public void onClientTick(TickEvent.ClientTickEvent event)
                 {
                     if (!this.activeEntities.isEmpty())
                         if (event.phase == Phase.START)
                         {
                             System.out.println("Size List : " + this.activeEntities.size());
                             for (IEntityAnimated entity : this.activeEntities)
                             {
                                 System.out.println("Size List 2 : " + this.activeEntities.size());
                                 System.out.println("SEMENCE: " + entity);
              
                                 entity.getAnimationHandler().animationsUpdate();
              
                                 if (((Entity) entity).isDead)
                                     this.removableEntities.add(entity);
                             }
                             System.out.println("Size List 3 : " + this.activeEntities.size());
                             for (IEntityAnimated entity : this.removableEntities)
                                 this.activeEntities.remove(entity);
                             this.removableEntities.clear();
                         }
                 }
              
                 // Called when the server ticks. Usually 20 ticks a second.
                 @SubscribeEvent
                 @SideOnly(Side.SERVER)
                 public void onServerTick(TickEvent.ServerTickEvent event)
                 {
                     if (!this.activeEntities.isEmpty())
                         if (event.phase == Phase.START)
                         {
                             System.out.println("Size List : " + this.activeEntities.size());
                             for (IEntityAnimated entity : this.activeEntities)
                             {
                                 System.out.println("Size List 2 : " + this.activeEntities.size());
                                 System.out.println("SEMENCE: " + entity);
              
                                 entity.getAnimationHandler().animationsUpdate();
              
                                 if (((Entity) entity).isDead)
                                     this.removableEntities.add(entity);
                             }
                             System.out.println("Size List 3 : " + this.activeEntities.size());
                             for (IEntityAnimated entity : this.removableEntities)
                                 this.activeEntities.remove(entity);
                             this.removableEntities.clear();
                         }
                 }
              
                 // Called when a new frame is displayed (See fps)
                 @SubscribeEvent
                 @SideOnly(Side.CLIENT)
                 public void onRenderTick(TickEvent.RenderTickEvent event)
                 {}
              
                 // Called when the world ticks
                 @SubscribeEvent
                 public void onWorldTick(TickEvent.WorldTickEvent event)
                 {}
              }
              

              :::

              Mais le problème à l’air de ce résoudre avec une CopyOnWriteArrayList mais créant un autre problème, une boucle infinie au même endroit</ientityanimated></ientityanimated></ientityanimated></ientityanimated>

              1 Reply Last reply Reply Quote 0
              • SCAREX
                SCAREX last edited by

                Si ça marche pas, soit faut faire un bloc synchronized, soit créer une copie de la liste

                1 Reply Last reply Reply Quote 0
                • RedRelay
                  RedRelay Moddeurs confirmés last edited by

                  Tu peux nous dire a quoi servent tes listes ?

                  1 Reply Last reply Reply Quote 0
                  • Ama
                    Ama last edited by

                    Mes liste sevent à enregistrer/supprimer les entités qui peuvent êtres animée ou non grâce à l’interface EntityAnimated

                    Cette erreur de “concurrence” arrive une fois le patch de la classe du Joueur autrement je n’ai pas cette erreur (mais le joueur n’est pas animé snif)

                    1 Reply Last reply Reply Quote 0
                    • RedRelay
                      RedRelay Moddeurs confirmés last edited by

                      Pourquoi tu te sers de 2 listes alors ?

                      1 Reply Last reply Reply Quote 0
                      • Ama
                        Ama last edited by

                        Effectivement, j’ai pas approfondi le code, qui n’est pas de moi à la base (jettez moi des cailloux) je rectifie le code donc

                        1 Reply Last reply Reply Quote 0
                        • J
                          Jodge last edited by

                          Je pense que l’erreur vient bêtement de ta fonction addEntity.
                          Le truc c’est que ta List est déjà utilisé la majeur partie du temps par l’événement TickEvent.

                          Je ne citerai qu’un bout du tuto sur la synchronisation de developpez.com :

                          Évitez les anciennes Collections datant de Java 1.0 (Vector, Hashtable…) qui sont par défaut synchronisées, mais utilisez les nouvelles datant de Java 1.2 (ArrayList, HashMap…) qui ne sont pas synchronisées (meilleures performances). Pour récupérer une vue synchronisée d’une Collection, il suffit de faire Collections.synchronizedCollection(Collection).

                          Si la solution de copie synchro ne fonctionne pas, tu peux toujours te tourner vers les mutex.

                          1 Reply Last reply Reply Quote 0
                          • RedRelay
                            RedRelay Moddeurs confirmés last edited by

                            Le problème existera toujours avec une vue synchronisée car les iterators ne sont pas thread-safe.
                            Il faut soit-même faire un iterator thread-safe ou effectuer une synchronisation global la portion de code qui utilise l’iterator.

                            1 Reply Last reply Reply Quote 0
                            • AymericRed
                              AymericRed last edited by

                              Ou juste copier la liste avant l’itération, et créer une liste d’éléments à supprimer après l’itération.

                              1 Reply Last reply Reply Quote 0
                              • J
                                Jodge last edited by

                                Cloner des listes n’est pas forcément une bonne idée, pour peu qu’elle soit grosse… Surtout qu’on parle ici d’une fonction appeler très régulièrement…

                                Le mieux niveau performance restera sans doute le mutex…

                                1 Reply Last reply Reply Quote 0
                                • RedRelay
                                  RedRelay Moddeurs confirmés last edited by

                                  @‘AymericRed’:

                                  Ou juste copier la liste avant l’itération, et créer une liste d’éléments à supprimer après l’itération.

                                  Ce qui donnera des problèmes de synchronisations de données et des problèmes de performances

                                  1 Reply Last reply Reply Quote 0
                                  • 1 / 1
                                  • First post
                                    Last post
                                  Design by Woryk
                                  Contact / Mentions Légales / Faire un don

                                  MINECRAFT FORGE FRANCE © 2018

                                  Powered by NodeBB