Question

Je travaille sur un projet java avec mon équipe au travail. En résumé, nous avons une classe principale qui a une méthode qui instancie et appelle une classe « Enregistrer ». Cette classe « Enregistrer » enregistre les fichiers à un serveur avec deux constructeurs et une poignée de méthodes visibles et non visibles. La classe est temps CPU intensive et qui empêche l'application principale d'afficher une fenêtre de dialogue de barre de progression permettant à l'utilisateur de connaître l'état de la sauvegarde. On m'a demandé de modifier la classe « Enregistrer » d'une manière qui il va produire de son propre fil de sorte que le reste de l'application principale peut faire les petites tâches d'affichage des informations à l'utilisateur.

Voici un concept général de celui-ci:   

class MainApp{  
    ...

    private void doSave()
    {
        Save s = new Save();
        StatusWindow sw = new StatusWindow();

        if save_this
          s.saveThis(sw);
        if save_that
          s.saveThat(sw);

        ...
    }
    ...
}

class Save{
   ...

   public void saveThis(StatusWindow s)
   {
       //alot of code
       s.update;

   }
   public void saveThat(StatusWindow s)
   {
       //alot of code
       s.update;
   }
   ... // some non-visible methods, even more code
 }

Je suis actuellement un novice avec des fils en Java, mais j'ai une compréhension de base de la façon dont ils travaillent. D'après ce que je comprends, une classe qui implémente Runnable, lorsqu'il est instancié comme un nouveau thread, la méthode run () est exécutée. Le problème est, car il existe différentes méthodes pour différents types de sauvegardes pour différents types de fichiers, comment puis-je mettre en œuvre ces méthodes dans la méthode run ()? La méthode run () la seule méthode qui est exécuté lorsque la classe est instancié dans un nouveau thread et .start () est appelée à ce sujet?

Quelle serait une bonne solution à ce problème? Est-ce que la nécessité de la classe « Enregistrer » pour être repensée pour mettre en œuvre l'ont Runnable?

Si plus de détails sont nécessaires, s'il vous plaît laissez-moi savoir. Merci pour tout! Aperçu

Mise à jour: Merci à tous pour l'aide! Ces solutions seront utiles pour l'avenir.

Était-ce utile?

La solution

La façon la plus simple est de faire un runnable pour chacun. Au lieu de paramètres étant passé dans l'exécution, en font des champs d'instance.

class SaveThatCommand implements Runnable {
     private final StatusWindow s;
     //constructor that initializes s
     public void run() {
        //save that code
        s.update();
     }
}

Un moyen plus facile d'y arriver, en fonction de vos besoins, est de faire une classe interne anonyme

public void doSave(final StatusWindow s) {
    if (saveThis) {
        Thread t = new Thread( new Runnable() {
            public void run() {
               saveThis(s);
            }
        });
        t.start();
    }
    //...
}

Et vous êtes un peu incorrect:. La méthode d'exécution est exécutée quand il est passé dans le constructeur d'un fil puis start () est appelée sur ce thread

Autres conseils

Vos collègues appellent probablement de plus Enregistrer un endroit dans l'application principale et souhaite éviter d'avoir à changer tout autre code pour soutenir l'enregistrement comme une opération parallèle. , En général, la plupart des gens ne préfèrent pas aussi faire leurs propres fils et au lieu préfèrent utiliser un ExecutorService. Voici donc comment le faire avec seulement modifier la classe Save et en utilisant un exécuteur testamentaire:

class Save{
   private static final ExecutorService executor = Executors.newCachedThreadPoolExecutor();
   //or fixed, or whatever you want. Maybe single thread executor is best if the Save code is not well suited to concurrency.

   static {
       Runtime.getRuntime().addShutdownHook(
           new Thread() {
               public void run() {
                   executor.shutdown();
               }
           }
       );
   }

   public void saveThis(StatusWindow s)
   {
      executor.execute(new SaveThis(s));
   }
   public void saveThat(StatusWindow s)
   {
      executor.execute(new SaveThat(s));
   }
   ... // some non-visible methods, even more code

   private class SaveThis implements Runnable {
       //StatusWindow member variable and constructor
       public void run() {
           //alot of code
           s.update;
       }
   }

   private class SaveThat implements Runnable {
       //StatusWindow member variable and constructor
       public void run() {
           //alot of code
           s.update;
       }
   }
 }

Une solution complète serait d'étendre la classe Runnable et passer les paramètres requis et le type de sauvegarde nécessaire au constructeur. Ensuite, vous pouvez les exécuter avec:

new Thread(saveRunnable).start();

Une solution plus simple serait de mettre en œuvre un modèle comme celui-ci dans la classe save:

public void saveThis(StatusWindow s) {
  Runnable r = new Runnable() {
     private StatusWindow s;
     public Runnable setStatusWindow(StatusWindow s) {
       this.s = s;
       return this;
     }

     @Override
     public void run() {
       this.Save.saveThisInternal(this.s);
     }
  }.setStatusWindow(s);
  new Thread(r).start();
}

public void saveThisInternal(StatusWindow s) {
  //alot of code
  s.update();
}

Il y a deux façons de le faire:

a) Vous pouvez déplacer le code avec le cas du bloc dans la méthode run ().

b) Vous pouvez avoir une classe par type de document qui implémente Runnable.

L'approche a) est plus simple car il nécessite moins de modifications au code existant. Mais l'approche b) est la manière orientée objet de le faire. « Une classe par tâche »

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top