Question

J'ai 2 matrices et je dois les multiplier, puis imprimer les résultats de chaque cellule. Dès qu'une cellule est prêt, je dois l'imprimer, mais par exemple, je dois imprimer [0] [0] cellule avant cellule [2] [0], même si le résultat de [2] [0] est prêt premier . Donc, je dois l'imprimer par commande. Donc, mon idée est de faire le fil de l'imprimante attendre jusqu'à ce que le multiplyThread il informe que la cellule correcte est prête à imprimer, puis le printerThread imprime la cellule et revenir à l'attente et ainsi de suite ..

J'ai donc ce thread qui fait la multiplication:

public void run() 
{
    int countNumOfActions = 0; // How many multiplications have we done
    int maxActions = randomize(); // Maximum number of actions allowed

    for (int i = 0; i < size; i++)
    {       
        result[rowNum][colNum] = result[rowNum][colNum] + row[i] * col[i];
        countNumOfActions++;
        // Reached the number of allowed actions
        if (countNumOfActions >= maxActions)
        {
            countNumOfActions = 0;
            maxActions = randomize();
            yield();
        }   
    }
    isFinished[rowNum][colNum] = true;
    notify();
}

Discussion qui imprime le résultat de chaque cellule:

public void run()
{
    int j = 0; // Columns counter
    int i = 0; // Rows counter
    System.out.println("The result matrix of the multiplication is:");

    while (i < creator.getmThreads().length)
    {
        synchronized (this)
        {
            try 
            {
                this.wait();
            } 
            catch (InterruptedException e1) 
            {
            }
        }
        if (creator.getmThreads()[i][j].getIsFinished()[i][j] == true)
        {
            if (j < creator.getmThreads()[i].length)
            {
                System.out.print(creator.getResult()[i][j] + " ");
                j++;
            }
            else
            {
                System.out.println();
                j = 0;
                i++;
                System.out.print(creator.getResult()[i][j] + " ");
            }
        }
    }

Maintenant, il me jette ces exceptions:

Exception in thread "Thread-9" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-6" Exception in thread "Thread-4" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-5" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-8" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-7" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-11" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-10" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)
Exception in thread "Thread-12" java.lang.IllegalMonitorStateException
    at java.lang.Object.notify(Native Method)
    at multiplyThread.run(multiplyThread.java:49)

ligne 49 multiplyThread est « notify () » .. Je pense que je dois utiliser le différemment mais je suis synchronisé ne sais pas comment.

Si quelqu'un peut aider ce code à travailler, je l'apprécie vraiment.

Était-ce utile?

La solution

Pour pouvoir appeler notify () vous devez synchroniser sur le même objet.

synchronized (someObject) {
    someObject.wait();
}

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}

Autres conseils

Lors de l'utilisation du wait et des méthodes de notify ou notifyAll en Java les choses suivantes doivent se rappeler:

  1. Utiliser notifyAll au lieu de notify si vous attendre à ce que plus d'un fil sera en attente d'une serrure.
  2. Les méthodes de wait et notify doit être appelé dans un contexte synchronisé . Voir le lien pour une explication plus détaillée.
  3. Il faut toujours appeler la méthode wait() dans une boucle parce que si plusieurs threads sont en attente d'une serrure et un d'entre eux a obtenu le verrou et réinitialiser l'état, puis les autres threads doivent vérifier l'état après qu'ils se réveillent pour voir s'ils ont besoin à nouveau attendre ou commencer le traitement.
  4. Utilisez le même objet pour appeler wait() et méthode notify(); chaque objet a sa propre serrure afin d'appeler wait() sur l'objet A et notify() sur l'objet B aucun sens.

Avez-vous besoin d'enfiler du tout? Je me demande la taille de vos matrices sont, et s'il n'y a aucun avantage à avoir un fil d'impression tandis que l'autre fait la multiplication.

Peut-être qu'il serait utile de mesurer ce temps avant de faire le travail de filetage relativement complexe?

Si vous avez besoin de fil, je créerais « n » threads pour effectuer la multiplication des cellules (peut-être « n » est le nombre de cœurs disponibles pour vous), puis utilisez la balise ExecutorService et Future mécanisme à être envoyé plusieurs multiplications simultanément.

De cette façon, vous pouvez optimiser le travail en fonction du nombre de cœurs, et que vous utilisez les outils de filetage Java plus haut niveau (ce qui devrait faciliter la vie). Écrivez les résultats dans une matrice de réception, puis il suffit d'imprimer cette fois toutes vos tâches futures ont terminé.

Disons que vous avez l'application « boîte noire » avec une classe nommée BlackBoxClass qui a méthode doSomething();.

En outre, vous avez observateur ou auditeur nommé onResponse(String resp) qui sera appelé par BlackBoxClass après le temps inconnu.

Le flux est simple:

private String mResponse = null; 
 ...
BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();
...
@override
public void onResponse(String resp){        
      mResponse = resp;       
}

Disons que nous ne savons pas ce qui se passe avec BlackBoxClass et quand nous devrions obtenir une réponse, mais vous ne voulez pas continuer votre code jusqu'à ce que vous obtenez réponse ou en d'autres termes obtenir appel onResponse. Ici, entre dans 'aide Synchronize':

public class SyncronizeObj {
public void doWait(long l){
    synchronized(this){
        try {
            this.wait(l);
        } catch(InterruptedException e) {
        }
    }
}

public void doNotify() {
    synchronized(this) {
        this.notify();
    }
}

public void doWait() {
    synchronized(this){
        try {
            this.wait();
        } catch(InterruptedException e) {
        }
    }
}
}

Maintenant, nous pouvons mettre en œuvre ce que nous voulons:

public class Demo {

private String mResponse = null; 
 ...
SyncronizeObj sync = new SyncronizeObj();

public void impl(){

BlackBoxClass bbc = new BlackBoxClass();
   bbc.doSomething();

   if(mResponse == null){
      sync.doWait();
    }

/** at this momoent you sure that you got response from  BlackBoxClass because
  onResponse method released your 'wait'. In other cases if you don't want wait too      
  long (for example wait data from socket) you can use doWait(time) 
*/ 
...

}


@override
public void onResponse(String resp){        
      mResponse = resp;
      sync.doNotify();       
   }

}

Vous ne pouvez appeler informer sur les objets où vous possédez leur moniteur. Donc, vous avez besoin de quelque chose comme

synchronized(threadObject)
{
   threadObject.notify();
}

notify() doit être synchronisé et

Je vais vous montrer bon exemple simple, la bonne façon d'utiliser wait et notify en Java. Je vais créer deux classe nommée ThreadA ThreadB . ThreadA appellera ThreadB.

public class ThreadA {
    public static void main(String[] args){
        ThreadB b = new ThreadB();//<----Create Instance for seconde class
        b.start();//<--------------------Launch thread

        synchronized(b){
            try{
                System.out.println("Waiting for b to complete...");
                b.wait();//<-------------WAIT until the finish thread for class B finish
            }catch(InterruptedException e){
                e.printStackTrace();
            }

            System.out.println("Total is: " + b.total);
        }
    }
} 

et pour la classe ThreadB:

class ThreadB extends Thread{
    int total;
    @Override
    public void run(){
        synchronized(this){
            for(int i=0; i<100 ; i++){
                total += i;
            }
            notify();//<----------------Notify the class wich wait until my    finish 
//and tell that I'm finish
            }
        }
    }

on peut appeler notifier à reprendre l'exécution des objets en attente comme

public synchronized void guardedJoy() {
    // This guard only loops once for each special event, which may not
    // be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}

reprendre en invoquant notification sur un autre objet de la même classe

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}

Utilisation simple si vous voulez Comment exécuter alternativement threads: -

public class MyThread {
    public static void main(String[] args) {
        final Object lock = new Object();
        new Thread(() -> {
            try {
                synchronized (lock) {
                    for (int i = 0; i <= 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + "A");
                        lock.notify();
                        lock.wait();
                    }
                }
            } catch (Exception e) {}
        }, "T1").start();

        new Thread(() -> {
            try {
                synchronized (lock) {
                    for (int i = 0; i <= 5; i++) {
                        System.out.println(Thread.currentThread().getName() + ":" + "B");
                        lock.notify();
                        lock.wait();
                    }
                }
            } catch (Exception e) {}
        }, "T2").start();
    }
}
  

réponse: -

T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B

Pour ce problème particulier, pourquoi ne pas stocker vos différents résultats dans les variables, puis lorsque le dernier de votre fil est traité, vous pouvez imprimer dans le format que vous voulez. Ceci est particulièrement utile si vous utilisez va être l'histoire de votre travail dans d'autres projets.

Cela ressemble à une situation pour le modèle producteur-consommateur. Si vous utilisez Java 5 ou, vous pouvez envisager d'utiliser la file d'attente de blocage (java.util.concurrent.BlockingQueue) et laisser le travail de coordination de fil à la mise en œuvre cadre / api sous-jacent. Voir l'exemple de java 5: http://docs.oracle.com /javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html ou java 7 (même exemple): http://docs.oracle.com/javase /7/docs/api/java/util/concurrent/BlockingQueue.html

Vous avez bien gardé votre bloc de code lorsque vous appelez méthode wait() en utilisant synchronized(this).

Mais vous n'avez pas pris même précaution lorsque vous appelez méthode notify() sans utiliser le bloc surveillé: synchronized(this) ou synchronized(someObject)

Si vous faites référence à la page de documentation Oracle sur classe, qui contient wait(), notify(), les méthodes de notifyAll(), vous pouvez voir ci-dessous précaution dans ces trois méthodes

  

Cette méthode ne doit être appelée par un fil qui est le propriétaire du moniteur de cet objet

Beaucoup de choses ont changé en 7 dernières années et nous allons avoir examiner d'autres alternatives à synchronized en questions ci-dessous SE:

Pourquoi utiliser un ReentrantLock si l'on peut utilisation synchronisée (cela)?

synchronisation vs verrouillage

Évitez synchronisées (cela) en Java?

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