2010-02-14 3 views
3

J'ai essayé de résoudre un problème impliquant la communication de thread en utilisant wait() et notify(). Fondamentalement, j'ai 2 threads T1 et T2 et je veux qu'ils soient exécutés dans l'ordre suivantSynchronisation de threads - Comment exécuter des threads alternativement

T1, T2, T1, T2 ..... Comment puis-je y parvenir?

Problème actuel: Il y a 2 threads T1 - qui imprime des nombres impairs (disons 1 - 100) et T2 - qui imprime des nombres pairs (1 - 100). Maintenant, la sortie devrait être 1, 2, 3, 4, 5, .... 100

+3

Exécutez les tâches dans un seul thread? –

+0

Pourquoi lancez-vous des threads si vous voulez synchroniser quelque chose? – Guy

+0

Je génère deux threads. Je veux qu'ils soient exécutés en alternance avec le premier thread exécuté en premier –

Répondre

2

Vous décrivez un modèle Producteur-Consommateur.

Ses implémentations Java sont décrites dans de nombreux livres Java, y compris M.Grand "Patterns in Java, Volume I" et "Java 2: The Complete Reference" par Naughton et Schildt.

Idée de base: les deux threads doivent utiliser un moniteur (c'est-à-dire que leur code doit se trouver à l'intérieur des blocs synchronized(monitor) {}). Vous avez également besoin d'une variable de drapeau qui devrait indiquer lequel des deux threads devrait fonctionner pour le moment.

Lorsque l'un de vos threads est à l'intérieur du bloc synchronisé, il doit vérifier la variable d'indicateur si c'est à son tour de faire le travail. Si oui, laissez-le fonctionner, puis modifiez la valeur de l'indicateur, puis notifiez tous les threads en attente. Si non, alors il devrait attendre.

+0

Ce n'est pas exactement ça.Fondamentalement, j'ai 2 fils, disons un imprime un et un autre imprime b. Maintenant, je veux imprimer une séquence ababab ..... –

+2

@sai vous pouvez utiliser une solution pour le producteur-consommateur comme solution pour cela. –

1

Vous essayez de paralléliser un processus en plusieurs étapes, n'est-ce pas? Si oui, voir ma réponse here pour une approche et un code de travail pour le faire. La réponse implique un ExecutorService (ou deux) et une ou plusieurs files d'attente de travail.

Pour cette approche, votre traitement doit pouvoir s'intégrer dans Runnable, avec des informations d'état intermédiaires pour le traitement. Vous alimentez chaque étape au ExecutorService en tant que Runnable, ce qui ajoute un second Runnable pour effectuer l'étape suivante. Ceci maintient l'ordre d'exécution, mais vous permet d'exécuter autant de threads que vous le souhaitez en parallèle.

: EDIT:

Comme autre a suggéré, la classe bibliothèque Exchanger peut être utilisé pour cela si vous voulez explicitement limiter le traitement à 2 fils. Je préfère l'approche ci-dessus car elle maintient l'ordre d'exécution et vous permet d'utiliser pleinement les systèmes modernes à 4 cœurs (et à 8 cœurs). Cela devrait aussi réduire un peu la synchronisation.

2

regard sur le paquet de java.util.concurrent, en particulier le Exchanger

0

Si T1 et T2 sont 2 différentes implémentations de l'interface Runnable, avec T1 étant un fil qui imprime des nombres impairs seulement (1,3 ,. ..) et T2 étant celui qui imprime le nombre pair (1,2 .....), ceci peut être fait en utilisant les méthodes wait() et notify() sur un moniteur partagé. L'important est que chaque thread vérifie un drapeau partagé avant d'en imprimer la valeur. Le code ci-dessous fonctionne;

//The shared monitor 
public class Mutex { 
public static boolean oddFlag; 

} 

//The Thread that is supposed to print Odd numbers (assuming an upper limit of 99) 
public class OddPrinter implements Runnable { 
private Mutex mutex; 

public OddPrinter(Mutex mutex) { 
    this.mutex = mutex; 
} 

public synchronized void run() { 
    System.out.println("Started Thread: OddPrinter"); 
    int i; 
    for(i=1; i<100; i+=2) { 
     synchronized (mutex) { 
      while(!Mutex.oddFlag) { 
       try { 
        mutex.wait(); 
       } catch (InterruptedException ie) { 
        Thread.currentThread().interrupted(); 
       } 
      } 

      if(Mutex.oddFlag == true) { 
       System.out.println("Print from OddPrinter: "+i); 
       Mutex.oddFlag = false; 
       mutex.notify(); 
      } 


     } 
    } 
    System.out.println("Finished Thread: OddPrinter: "+i); 
} 

} 

//The Thread that is supposed to print Odd numbers (assuming an upper limit of 98) 
public class EvenPrinter implements Runnable { 
private Mutex mutex; 

public EvenPrinter(Mutex mutex) { 
    this.mutex = mutex; 
} 

public synchronized void run() { 
    System.out.println("Started Thread: EvenPrinter"); 
    int i; 
    for(i=2; i<100; i+=2) { 
     synchronized (mutex) { 
      while(Mutex.oddFlag) { 
       try { 
        mutex.wait(); 
       } catch (InterruptedException ie) { 
        Thread.currentThread().interrupted(); 
       } 
      } 

      if(!(Mutex.oddFlag == true)) { 
       System.out.println("Print from EvenPrinter: "+i); 
       Mutex.oddFlag = true; 
       mutex.notify(); 
      } 

     } 
    } 
    System.out.println("Finished Thread: EvenPrinter: "+i); 
} 

} 

//The test harness that executes the threads 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 
import java.util.concurrent.TimeUnit; 

public class NumberPrinterTest { 

public static void main(String[] args) throws Exception{ 
    ExecutorService es = Executors.newFixedThreadPool(2); 

    Mutex mutex = new Mutex(); 
    OddPrinter op = new OddPrinter(mutex); 
    EvenPrinter ep = new EvenPrinter(mutex); 
    Mutex.oddFlag = true; 
    es.execute(op); 
    es.execute(ep); 

    if(null != es){ 
     es.shutdown(); 
     try { 
      es.awaitTermination(1, TimeUnit.MINUTES); 
     } catch (InterruptedException e) { 
      Thread.currentThread().interrupted(); 
     } 
    } 

} 

} 
Questions connexes