Domanda

Ho 2 matrici e ho bisogno di moltiplicare loro e quindi stampare i risultati di ogni cella. Non appena una cella è pronta ho bisogno di stamparlo, ma per esempio ho bisogno di stampare il [0] [0] cella prima cellula [2] [0], anche se il risultato di [2] [0] è pronto prima . Così ho bisogno di stamparlo per ordine. Quindi la mia idea è quella di rendere l'attesa fino a quando il filo della stampante multiplyThread di informarla che la cella corretta è pronto per essere stampato e poi il printerThread stamperà la cella e tornare ad aspettare e così via ..

Così ho questa discussione che fa la moltiplicazione:

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

Discussione che stampa il risultato di ogni cella:

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

Ora mi lancia queste eccezioni:

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)

linea 49 in multiplyThread è la "notifica ()" .. Penso che ho bisogno di usare il sincronizzati in modo diverso, ma io non sono sicuro di come.

Se qualcuno può aiutare questo codice per lavorare io realmente lo apprezzerei.

È stato utile?

Soluzione

Per essere in grado di chiamare notify () è necessario sincronizzare sullo stesso oggetto.

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

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

Altri suggerimenti

Durante l'utilizzo del wait e notify o notifyAll metodi in Java le seguenti cose devono essere ricordati:

  1. Usa notifyAll invece di notify se ci si aspetta che più di un thread sarà in attesa di un blocco.
  2. I metodi wait e notify deve essere chiamato in un contesto sincronizzato. Vedi il link per una spiegazione più dettagliata.
  3. chiamare sempre il metodo wait() in un ciclo perché se più thread sono in attesa di un blocco e uno di loro ha ottenuto il blocco e ripristinare la condizione, poi gli altri thread devono verificare le condizioni dopo si svegliano per vedere se hanno bisogno aspettare ancora o può avviare l'elaborazione.
  4. Utilizza lo stesso oggetto per chiamare wait() e il metodo notify(); ogni oggetto ha un proprio lucchetto in modo da chiamare wait() su un oggetto A e notify() su oggetto B non ha alcun senso.

Avete bisogno di infilare questo a tutti? Mi chiedo quanto è grande il tuo matrici sono, e se non c'è alcun beneficio nell'avere stampa un thread, mentre l'altro fa la moltiplicazione.

Forse varrebbe la pena di misurare questa volta prima di fare il relativamente complesso lavoro threading?

Se si ha bisogno di infilarlo, vorrei creare 'n' thread per eseguire la moltiplicazione delle cellule (forse 'n' è il numero di core disponibili a voi), e quindi utilizzare il ExecutorService e Future meccanismo inviano più moltiplicazioni contemporaneamente.

In questo modo è possibile ottimizzare il lavoro in base al numero di core, e si sta utilizzando il livello più alto Java strumenti di filettatura (che dovrebbe rendere la vita più facile). Scrivi i risultati di nuovo in una matrice di ricezione, e poi semplicemente stampare una volta tutte le attività future hanno completato.

Diciamo che avete applicazione 'scatola nera' con una certa classe denominata BlackBoxClass che ha metodo doSomething();.

Inoltre, si dispone di osservatore o ascoltatore chiamato onResponse(String resp) che verrà chiamato da BlackBoxClass dopo tempo sconosciuto.

Il flusso è semplice:

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

Diciamo che non sappiamo cosa sta succedendo con BlackBoxClass e quando dovremmo ottenere risposta, ma non si desidera continuare il tuo codice fino ad ottenere risposta o in altre parole ottiene chiamata onResponse. Qui entra 'Sincronizza helper':

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

Ora possiamo realizzare ciò che vogliamo:

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

}

È possibile chiamare solo informare sugli oggetti in cui si è proprietari il loro monitor. Quindi è necessario qualcosa di simile

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

notify() deve essere sincronizzata così

Ti destra semplice esempio ti mostri il modo giusto di usare wait e notify in Java. Così creerò due classe denominata ThreadA e ThreadB . ThreadA chiamerà 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);
        }
    }
} 

e per 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
            }
        }
    }

possiamo chiamare notifica di riprendere l'esecuzione di oggetti in attesa come

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

riprendere questo invocando notifica su un altro oggetto della stessa classe

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

Uso semplice se si vuole come eseguire le discussioni in alternativa: -

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

Risposta: -

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

Per questo particolare problema, perché non memorizzare i vostri vari risultati nelle variabili e poi quando l'ultimo del tuo thread viene elaborato è possibile stampare in qualsiasi formato desiderato. Ciò è particolarmente utile se si sta andando utilizzare la storia del lavoro in altri progetti.

Questo appare come una situazione per modello produttore-consumatore. Se stai usando Java 5 o fino, si può considerare l'utilizzo della coda di blocco (java.util.concurrent.BlockingQueue) e lasciare il lavoro di coordinamento filo alla realizzazione quadro / api sottostante. Vedere l'esempio da Java 5: http://docs.oracle.com /javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html o Java 7 (stesso esempio): http://docs.oracle.com/javase /7/docs/api/java/util/concurrent/BlockingQueue.html

Hai correttamente custodito il tuo blocco di codice quando si chiama il metodo wait() utilizzando synchronized(this).

Ma non avete preso stessa precauzione quando si chiama il metodo notify() senza l'utilizzo di blocco sorvegliato: synchronized(this) o synchronized(someObject)

Se si fa riferimento alla pagina di documentazione Oracle su classe, che contiene wait(), notify(), metodi notifyAll(), potete vedere qui sotto precauzione in tutti questi tre metodi

  

Questo metodo deve essere chiamato solo da un filo che è il proprietario di controllo di questo oggetto

Molte cose sono cambiate negli ultimi 7 anni e diamo un'occhiata in altre alternative per synchronized in seguito domande SE:

Perché utilizzare un ReentrantLock se si può utilizzare sincronizzato (questo)?

Sincronizzazione vs blocco

Evitare sincronizzato (questo) in Java?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top