Frage

Ich habe zwei Matrizen und muss sie multiplizieren und dann die Ergebnisse jeder Zelle ausdrucken.Sobald eine Zelle fertig ist, muss ich sie drucken, aber ich muss zum Beispiel die Zelle [0][0] vor der Zelle [2][0] drucken, auch wenn das Ergebnis von [2][0] zuerst fertig ist .Also muss ich es auf Bestellung ausdrucken.Meine Idee ist es also, den Druckerthread warten zu lassen, bis der multiplyThread benachrichtigt es, dass die richtige Zelle zum Drucken bereit ist und dann printerThread druckt die Zelle aus und kehrt zum Warten zurück und so weiter.

Ich habe also diesen Thread, der die Multiplikation durchführt:

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();
}

Thread, der das Ergebnis jeder Zelle ausgibt:

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] + " ");
            }
        }
    }

Jetzt wirft es mir diese Ausnahmen:

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)

Linie 49 Zoll multiplyThread ist „notify()“. Ich denke, ich muss die Synchronisierung anders verwenden, bin mir aber nicht sicher, wie.

Wenn jemand dazu beitragen kann, dass dieser Code funktioniert, wäre ich sehr dankbar.

War es hilfreich?

Lösung

Um einen href zu nennen <= "http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Object.html#notify ()" rel = "noreferrer" > notify () auf demselben Objekt synchronisieren müssen.

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

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

Andere Tipps

Während der wait und notify oder notifyAll Methoden in Java unter Verwendung der folgenden Dinge erinnert werden müssen:

  1. Verwenden Sie notifyAll statt notify wenn Sie erwarten, dass mehr als ein Thread auf eine Sperre warten.
  2. Die wait und notify Methoden muss aufgerufen werden, in synchronisierter Zusammenhang . Siehe den Link für eine ausführlichere Erklärung.
  3. Sie immer die wait() Methode in einer Schleife nennen, weil, wenn mehrere Threads auf eine Sperre warten und einer von ihnen die Sperre bekam und den Zustand zurückgesetzt, dann die anderen Threads müssen den Zustand überprüfen, nachdem sie aufwachen, um zu sehen, ob sie brauchen wieder warten oder Verarbeitung beginnen kann.
  4. Verwenden Sie das gleiche Objekt für wait() und notify() Methode aufrufen; jedes Objekt hat seine eigene Sperre so ruft wait() auf Objekt A und notify() auf Objekt B wird keinen Sinn machen.

Sie benötigen dies überhaupt einzufädeln? Ich frage mich, wie groß Ihre Matrizen sind, und ob es irgendeinen Vorteil ein Thread Druck in mit, während die andere die Vermehrung der Fall ist.

Vielleicht wäre es lohnt sich, diese Zeit zu messen, bevor der relativ komplexen Threading Arbeit zu tun?

Wenn Sie es Thread brauchen, würde ich schaffen ‚n‘ Fäden die Vermehrung der Zellen durchzuführen (vielleicht ‚n‘ ist die Anzahl der Kerne zur Verfügung), und verwenden Sie dann die ExecutorService und Future Mechanismus gleichzeitig mehrere Multiplikationen zu versenden.

Auf diese Weise können Sie die Arbeit optimieren auf der Anzahl der Kerne basieren, und Sie sind mit der höheren Ebene Java Threading Tool (was soll das Leben leichter machen). Schreiben Sie die Ergebnisse zurück in eine Aufnahmematrix und dann einfach drucken diese einmal alle Ihre zukünftigen Aufgaben abgeschlossen haben.

Angenommen, Sie haben mit einer gewissen Klasse mit dem Namen BlackBoxClass ‚Black Box‘ Anwendung, die Methode doSomething(); hat.

Ferner haben Sie Beobachter oder Zuhörer namens onResponse(String resp), die von BlackBoxClass nach unbekanntem Zeitpunkt aufgerufen werden.

Der Fluss ist einfach:

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

Lassen Sie uns sagen wir nicht wissen, was mit BlackBoxClass los ist und wenn wir Antwort erhalten sollten, aber Sie wollen nicht, Ihren Code fortsetzen, bis Sie Antwort erhalten oder in anderen Worten onResponse Anruf erhalten. Hier geht 'Synchronisieren Helfer':

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) {
        }
    }
}
}

Jetzt können wir das umsetzen, was wir wollen:

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();       
   }

}

Sie können nur auf Objekte informieren in dem Sie ihren Monitor besitzen. Sie müssen also so etwas wie

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

notify() muss ebenfalls synchronisiert werden

Ich bin gleich einfaches Beispiel zeigt Ihnen den richtigen Weg wait und notify in Java zu verwenden. Also werde ich zwei Klasse erstellen namens ThreadA & ThreadB . ThreadA wird ThreadB nennen.

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);
        }
    }
} 

und für die Klasse 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
            }
        }
    }

können wir rufen Sie benachrichtigen die Ausführung des Wartens Objekte wie

wieder aufnehmen
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!");
}

fortsetzen dies, indem Sie auf ein anderes Objekt der gleichen Klasse benachrichtigen Aufruf

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

Einfache Verwendung, wenn Sie wollen, wie Threads ausführen alternativ: -

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();
    }
}
  

Antwort: -

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

Warum speichern Sie für dieses spezielle Problem nicht Ihre verschiedenen Ergebnisse in Variablen, und wenn der letzte Teil Ihres Threads verarbeitet ist, können Sie ihn in jedem gewünschten Format drucken.Dies ist besonders nützlich, wenn Sie Ihren Arbeitsverlauf in anderen Projekten verwenden möchten.

Dies sieht aus wie eine Situation für Erzeuger-Verbraucher-Muster. Wenn Sie mit Java 5 oder oben, können Sie mit blockierenden Warteschlange (java.util.concurrent.BlockingQueue) prüft und den Faden Koordinationsarbeit an der darunter liegenden Rahmen / api Durchführung. Siehe das Beispiel aus Java 5: http://docs.oracle.com /javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html oder Java-7 (gleiches Beispiel): http://docs.oracle.com/javase /7/docs/api/java/util/concurrent/BlockingQueue.html

Sie haben Ihren Code-Block richtig bewacht, wenn Sie wait() Methode aufrufen durch synchronized(this) verwenden.

Aber Sie haben nicht gleichen Vorsichtsmaßnahmen getroffen, wenn Sie notify() Methode aufrufen, ohne bewachten Block mit: synchronized(this) oder synchronized(someObject)

Wenn Sie auf der Oracle-Dokumentation Seite auf Object Klasse, die wait() enthält, notify(), notifyAll() Methoden können Sie unten vorsorglich in all diesen drei Methoden finden Sie unter

  

Diese Methode sollte nur von einem Thread aufgerufen werden, der Besitzer dieses Objekts Monitor ist

Viele Dinge haben sich in den letzten 7 Jahren verändert worden und schauen wir uns in andere Alternativen müssen in folgenden SE Fragen synchronized:

Warum einen ReentrantLock verwenden, wenn man kann verwenden synchronisiert (this)?

Synchronisation vs sperren

Vermeiden synchronisiert (this) in Java?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top