2010-09-21 4 views
2

J'ai une méthode et un thread que je voudrais exécuter dans l'ordre suivant: D'abord la méthode devrait faire quelque chose avec un objet, et ensuite le thread devrait faire quelque chose avec l'objet. Ils partagent le même objet. Je dois les synchroniser, mais je ne fais que rencontrer Threads. Comment puis je faire ça?Synchronisez le thread et une méthode avec un objet?

private synchronized method() 
{ 
//do something with an object (a field) 
} 

Runnable ObjectUpdater = new Runnable() 
{ 
//do something with the object after the method has finished 
} 

Mon code, qui réussit à geler mon thread principal (où la méthode est) Mon code de fil:

private Runnable something = new Runnable(){ 
synchronized (this){ 
while (flag == false) 
{ try {wait();) 
catch (IntExc ie) {e.printStackTrace...} 
} 
//here it does its thing 
} 
setFlag(false); 
} 
My method code (part of the main thread) 
private void Method() 
{ 
//do its thing 
setFlag(true); 
notifyAll(); 
} 

Répondre

1

Pour moi, c'est des questions simples

"vous avez dit que je ne sais pas qui est va accéder à l'objet premier - le fil de ObjectUpdater séparé, ou le thread principal (avec la méthode) . Si le thread séparé, il accède avant que le thread principal , ce qui est mauvais et je ne veux que cela se produise »

si vous voulez que la principale méthode de fil pour appeler sapins t puis le thread objectUpdater, avoir un drapeau pour savoir si la méthode est visitée en premier par le thread principal, s'il est updater puis appelez wait à ce thread, une fois que le main termine l'appel notifier qui exécutera le thread de séparation, thread principal ou thread de mise à jour, définissez un nom pour le thread lors de sa création. et obtenez le nom Thread.currentThread(). getName().

1

En dehors de la synchronisation sur l'objet, vous pourriez appeler la méthode en tant que premier instruction dans le nouveau thread, ou vous pouvez démarrer le nouveau thread à la fin de la méthode.

Il est difficile de dire quelle est la meilleure approche dans votre cas, peut-être vous pouvez nous donner plus de détails sur le comment et quoi?

Mise à jour

En réponse à votre code (pour une raison quelconque, je ne peux pas ajouter un autre commentaire ...)

est la méthode appelée à partir d'un bloc synchronized(this)? Si ce n'est pas le notifyAll() devrait être dans un bloc synchronisé. Aussi, pouvez-vous mettre à jour le code pour montrer où/comment votre thread principal interagit avec la méthode et l'objet?

+0

J'ai un thread qui met à jour un composant de l'interface utilisateur. Et j'ai aussi le fil conducteur. Le thread principal initialise les éléments, sur lesquels le composant de l'interface utilisateur s'appuie. Pour être correctement dessinés, les éléments doivent être initialisés avant que le composant UI ne soit tracé. En outre, le thread principal, l'objet et le thread séparé ne sont pas dans la même classe. – George

+0

@George, le thread principal pourrait appeler la méthode pour mettre à jour l'objet avant de le faire connaître au thread de l'interface utilisateur. Si cela est impossible, synchroniser sur l'objet et introduire une méthode comme 'isInitialised()' de sorte que le thread d'interface utilisateur peut vérifier que l'objet est dans l'état correct après aquired la serrure. – rsp

+0

Merci, c'est ce que j'essaie de faire pour la meilleure partie d'une heure.J'ai fait un drapeau, et le thread de mise à jour de l'interface utilisateur attend "le feu vert" par le code suivant while (theNameOfMyFlag() == false) { try {wait} catch .... } // après ce bloc , faites ce qu'il devrait faire et dans mon fil principal - theNameOfMyFlag.set (true); notifyAll(); Log.d .... Le problème est typique - IlligalMonitorStateException, car l'objet n'est pas verrouillé avant "wait()". Si je verrouille l'objet via synchronized (this) ou ReentrantLock, mon application se bloque. Quelque chose ne va pas ... – George

0

Je pense que meilleure approche serait d'appeler la méthode à l'aide que vous voulez exécuter quelque chose avec un objet, puis déclarer le fil qui ferait quelque chose avec un objet.

1

Utilisez la classe Sémaphore pour permettre l'accès à l'objet.

public class Main 
{ 
    public static void main (String[] args) { 
    final Obj obj = new Obj(); 
    final Semaphore semaphore = new Semaphore(0); 
    Thread t = new Thread(new Runnable() { 
     @Override 
     public void run() { 
     try { 
     semaphore.acquire(); 
    } catch (InterruptedException ex) { 
     Thread.currentThread().interrupt(); 
     return; 
    } 
    obj.doSomething(); 
     } 
    }); 
    t.setName("test"); 
    t.start(); 

    try { 
     Thread.sleep(1000); 
    } catch (InterruptedException ignored) { 
    } 
    obj.doSomething(); 
    semaphore.release(); 
    } 
} 

class Obj { 

    public void doSomething() { 
    System.out.println("something done by " + Thread.currentThread()); 
    } 
} 
Questions connexes