132

2つの行列があり、それらを乗算してから、各セルの結果を出力する必要があります。1つのセルの準備ができたらすぐに印刷する必要がありますが、たとえば、[2] [0]の結果が最初に準備できたとしても、セル[2][0]の前に[0][0]セルを印刷する必要があります。 。だから私はそれを注文で印刷する必要があります。multiplyThreadしたがって、私の考えは、正しいセルを印刷する準備ができたことを通知するまでプリンタスレッドを待機さprinterThreadせてから、セルを印刷して待機に戻るなどです。

だから私は乗算を行うこのスレッドを持っています:

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

各セルの結果を出力するスレッド:

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

今、それは私にこれらの例外を投げます:

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)

49行目multiplyThreadは「notify()」です。同期を別の方法で使用する必要があると思いますが、方法がわかりません。

誰かがこのコードが機能するのを手伝ってくれるなら、私は本当に感謝します。

4

12 に答える 12

219

notify()を呼び出せるようにするには、同じオブジェクトで同期する必要があります。

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

/* different thread / object */
synchronized (someObject) {
    someObject.notify();
}
于 2009-05-20T08:21:52.957 に答える
64

waitJavaでandnotifyまたはorメソッドを使用するときはnotifyAll、次の点に注意する必要があります。

  1. 複数のスレッドがロックを待機することが予想される場合は、 notifyAllの代わりに使用してください。notify
  2. waitandメソッドはnotify、同期されたコンテキストで呼び出す必要があります。詳細な説明については、リンクを参照してください。
  3. wait()複数のスレッドがロックを待機していて、そのうちの1つがロックを取得して条件をリセットした場合、他のスレッドはウェイクアップ後に条件をチェックして、再度待機する必要があるかどうかを確認する必要があるため、常にループでメソッドを呼び出します。処理を開始できます。
  4. 呼び出しwait()notify()メソッドに同じオブジェクトを使用します。すべてのオブジェクトには独自のロックがあるためwait()、オブジェクトAとnotify()オブジェクトBを呼び出しても意味がありません。
于 2011-06-03T00:12:54.443 に答える
21

これをスレッド化する必要がありますか?私はあなたの行列がどれくらい大きいか、そして他のスレッドが乗算を行う間に一方のスレッドを印刷することに何か利点があるかどうか疑問に思っています。

おそらく、比較的複雑なスレッド作業を行う前に、今回は測定する価値がありますか?

スレッド化する必要がある場合は、セルの乗算を実行するために「n」スレッドを作成し(おそらく、「n」は使用可能なコアの数です)、ExecutorServiceおよびFutureメカニズムを使用して複数の乗算を同時にディスパッチします。 。

そうすれば、コアの数に基づいて作業を最適化でき、より高レベルのJavaスレッドツールを使用できます(これにより、作業が楽になります)。結果を受信マトリックスに書き戻し、将来のすべてのタスクが完了したら、これを印刷するだけです。

于 2009-05-20T08:34:37.517 に答える
14

BlackBoxClassメソッドを持つ名前のクラスを持つ「ブラックボックス」アプリケーションがあるとしましょうdoSomething();

さらに、不明な時間の後onResponse(String resp)に呼び出されるという名前のオブザーバーまたはリスナーがあります。BlackBoxClass

フローは単純です。

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

何が起こっているのかBlackBoxClass、いつ答えを得る必要があるのか​​わからないが、答えを得るまで、つまりonResponse電話をかけるまでコードを続けたくないとしましょう。ここに「Synchronizehelper」と入力します。

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

これで、必要なものを実装できます。

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

}
于 2012-10-15T22:25:20.020 に答える
7

モニターを所有しているオブジェクトに対してのみ通知を呼び出すことができます。だからあなたは次のようなものが必要です

synchronized(threadObject)
{
   threadObject.notify();
}
于 2009-05-20T08:23:12.953 に答える
6

notify()同様に同期する必要があります

于 2009-05-20T08:16:55.387 に答える
3

wait簡単な例で、Javaでの正しい使用方法を説明notifyします。そこで、ThreadAThreadBという名前の2つのクラスを作成します。ThreadAは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);
        }
    }
} 

およびクラス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
            }
        }
    }
于 2015-06-19T09:47:11.850 に答える
3

代わりにスレッドを実行する方法が必要な場合の簡単な使用:-

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

応答 :-

T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
T1:A
T2:B
于 2017-05-10T05:36:50.017 に答える
2

notifyを呼び出して、待機中のオブジェクトの実行を再開できます。

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

同じクラスの別のオブジェクトでnotifyを呼び出して、これを再開します

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}
于 2016-05-18T10:46:36.053 に答える
0

この特定の問題については、さまざまな結果を変数に保存して、スレッドの最後が処理されたときに、任意の形式で印刷できるようにしてください。これは、他のプロジェクトで作業履歴を使用する場合に特に便利です。

于 2014-06-01T01:52:17.600 に答える
0

これは、生産者/消費者パターンの状況のように見えます。java 5以降を使用している場合は、ブロッキングキュー(java.util.concurrent.BlockingQueue)の使用を検討し、スレッド調整作業を基盤となるフレームワーク/API実装に任せることができます。java 5の例を参照してください:http: //docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/BlockingQueue.html またはjava 7(同じ例): http://docs。 oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html

于 2014-11-06T17:33:20.863 に答える
0

wait()を使用してメソッドを呼び出すと、コードブロックが適切に保護されていますsynchronized(this)

notify()ただし、保護されたブロックを使用せずにメソッドを呼び出す場合は、同じ予防策を講じていません:synchronized(this)またはsynchronized(someObject)

、、メソッドを含むObjectクラスのOracleドキュメントページを参照すると、これら3つのメソッドすべての注意事項を以下に示すことができます。wait()notify()notifyAll()

このメソッドは、このオブジェクトのモニターの所有者であるスレッドによってのみ呼び出される必要があります

synchronized過去7年間で多くのことが変更されたので、以下のSEの質問で他の代替案を調べてみましょう。

同期(これ)を使用できるのに、なぜReentrantLockを使用するのですか?

同期とロック

Javaで同期(これ)を避けますか?

于 2016-05-22T09:55:58.267 に答える