2 votes

Comment puis-je ajouter des éléments à une liste à partir d'un fil de discussion et conserver l'ordre d'ajout ?

J'essaie d'ajouter des éléments dans une liste et de conserver l'ordre d'ajout. Le problème est que le problème est que l'ajout se fait dans un fil de discussion parce que je dois obtenir des détails de la base de données, les mettre dans un fichier
et l'ajouter à la liste.

public void addNewItem(Step item){

    Thread t = new Thread(new Runnable(){
        public void run() {
            item.setDetails(db.getStepDetails(step.getId()));
            add(item);
        }
    });

    t.start();
}

Le site add ressemble à une méthode :

private void add(Step step){
    mitems.add(step);
}

Si je fais quelque chose comme

 addNewItem(stepA);
 addNewItem(stepB);

Si le premier appel prend trop de temps, le deuxième élément est ajouté en premier dans ma liste.

Savez-vous comment je peux attendre qu'une action se termine avant de continuer à ajouter un autre élément dans ma liste ?

Merci.

0voto

P. Lalonde Points 599

Vous pourriez ajouter un bloc synchronisé ou utiliser un ReentrantLock.

Thread t = new Thread(new Runnable(){
    public void run() {
        synchronized(someSafeVar) {
            item.setDetails(db.getStepDetails(step.getId()));
            add(item);
        }
    }
});

De plus, si c'est seulement la méthode "add" qui prend du temps, cette méthode seulement pourrait être synchronisée.

0voto

Marco Forberg Points 2163

Vous pourriez conserver l'ordre des articles si vous ajoutez les articles à votre liste avant vous définissez les détails. Vous pourriez alors attendre avec toutes les actions suivantes jusqu'à ce qu'un drapeau initialisé de vos éléments soit activé :

mitems.add(stepA);
mitems.add(stepB)

[...]

ThreadGroup group = new ThreadGroup("GetStepDetailsGroup");

for(Step step : mitems)
{
    Thread thread = new Thread(group, new Runnable(){
        public void run() {
            item.setDetails(db.getStepDetails(step.getId()));
        }
    });

    thread.start();
}

while(group.activeCount() > 0) {
    try {
        Thread.sleep(50);
    } catch(InteruptedExpection e) {
        // ignored
    }
}

0voto

Jamie Points 279

Vous pourriez créer un seul fil de travail, et l'alimenter à partir d'une file d'attente, et ainsi vous auriez un fil unique ajoutant aux mitems.

Dans ce cas, vous devrez créer deux listes et les synchroniser.

EG,

List<Step> processingList = new ArrayList<Step>();
List<Step> mitems = new ArrayList<Step>();
public void addNewItem(Step item)
{
  syncrhonized(processingList)
  {
    processingList.add(item);
  }
}

Le fil de travail prend des éléments à l'avant de processingList, les traite et les ajoute à mitems lorsqu'ils sont prêts.

0voto

CloudyMarble Points 16155

Vous pourriez utiliser un dictionnaire à la place :

Dictionary mitems = new Hashtable();

et

mitems.put("1", item);

La clé serait alors l'Ordre.

0voto

Ralf H Points 853

Dans votre exemple, il semble que l'ajout des étapes à une liste soit totalement indépendant de la récupération des informations dans la base de données et du remplissage des étapes.

Par conséquent, vous pourriez simplement placer toutes vos étapes dans une liste en utilisant un seul fil. Ensuite, vous récupérez les informations de la base de données à l'aide de Runnables, un pour chaque étape, et vous exécutez ces Runnables dans un Executor avec autant de threads que vous le souhaitez (tout en bénéficiant d'un gain de vitesse grâce au multithreading).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X