2010-11-11 3 views
0

J'ai une situation où j'ai besoin d'appeler une méthode1() dans la classe B à partir de A. Lorsque la méthode1() est appelée, elle crée un nouveau thread dit (MyThread) et le lance immédiatement. Dans mon cas, j'appelle method1() de deux endroits différents dans l'application. Je ne veux pas créer une nouvelle instance de ce fil à chaque fois. Inside method1() j'ai essayé de vérifier si myThread.isAlive() avant de créer une nouvelle instance de MyThread. Mais j'obtiens une erreur de compilation MyThread doit être initialisé pour appeler MyThread.isAlive(). Donc, si mis dans une propriété de méthode de type Thread ie.,Avoir une référence de thread comme propriété de niveau de classe?

méthode() { Thread myThread; if (myThread.isAlive()) {return}; ..... }

Est-ce une bonne idée de déclarer une propriété de niveau classe dans classB pour Mythread et de l'initialiser à null. Puis, à l'intérieur de la méthode method1(), vérifiez l'état du thread s'il n'est pas en cours d'exécution, créez-en un nouveau?

class B() 
{ 
    Thread myThread = null; 
    public static B getInstance() 
    { 
     return B singleton object; 
    } 

    public void method1() 
    { 
    if(myThread.isAlive()) 
     return; 
    myThread = new Thread(new Runnable(){ 
     public void run(){ 
       do some stuff..... 
     }).start(); 
} 

==================

class A() 
{ 
    B.getInstance().method1(); 
} 

==================

class someOtherClass() 
{ 
    B.getInstance().method1(); 
} 

Répondre

0

Vous pouvez faire mieux en utilisant un Executor, plus précisément un fixed thread pool. Créez votre pool de threads dans le constructeur de B et gardez une référence finale privée. Puis soumettez les Runnables dans la méthode 1(), ne démarrez pas un nouveau thread. Cette approche présente plusieurs avantages: l'Executor gère correctement les problèmes du cycle de vie des threads, vous pouvez changer le modèle de thread pour augmenter les threads très facilement, et il n'y a pas de conditions de course (dans le code d'initialisation du thread - merci les commentateurs pour le signaler). Il peut y avoir des conditions de course à l'intérieur du Runnable que vous utilisez.

Edité pour ajouter un exemple:

class B() 
    { 
    private final Executor threadPool = Executors.newFixedThreadPool(1); 
    private boolean taskSubmmitted = false; 
    public static B getInstance() 
    { 
     return B singleton object; 
    } 

    public synchronized void method1() 
    { 
    if(taskSubmitted) 
     return; 
    myRunnable = new Runnable(){ 
     public void run(){ 
       do some stuff..... 
     }}; 
    threadPool.submit(myRunnable); 
    taskSubmitted = true; 
    } 
+0

Ça a l'air génial! mais pouvez-vous s'il vous plaît m'expliquer un peu plus avec des extraits de code modifiés de mon code? S'il vous plaît – AKh

+1

Vous pouvez en apprendre plus à ce sujet en lisant les tutoriels Java pertinents; par exemple. http://download.oracle.com/javase/tutorial/essential/concurrency/executors.html –

+1

Il ne peut y avoir aucune condition de concurrence dans le lancement du thread, mais ils sont toujours là lors de l'exécution des tâches, sauf si vous utilisez un seul thread exécuteur. –

0

Ce code provoquera une NullPointerException (NPE) d'être jeté lorsque vous premier appel method1, car il va tenter d'invoquer isAlive() sur null. Vous avez besoin if(myThread != null && myThread.isAlive())

+0

Oui j'oublié de mentionner que dans le code .. mais j'ai effectivement en place. – AKh

0
class B() 
{ 
      // class level variable works fine.... I dont see a problem 
    private Thread myThread = null; 

    public static B getInstance() 
    { 
    return B singleton object; 
    } 

    public void method1() 
    { 
    if(myThread != null && myThread.isAlive()) 
     return; 

    myThread = new Thread(new Runnable(){   
     public void run(){ 
      do some stuff..... 
     }).start(); 
    } 
} 
Questions connexes