2つのマトリックスがあり、それらを乗算してから各セルの結果を出力する必要があります。 1つのセルの準備ができたらすぐに印刷する必要がありますが、たとえば、[2] [0]の結果が最初に準備できていても、[0] [0]セルをセル[2] [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)
multiplyThread
の49行目は「notify()」です。同期を別の方法で使用する必要があると思いますが、どうすればよいかわかりません。
誰かがこのコードを機能させるのを手伝うことができれば、本当に感謝しています。
notify() を呼び出すには、同じオブジェクトで同期する必要があります。
synchronized (someObject) {
someObject.wait();
}
/* different thread / object */
synchronized (someObject) {
someObject.notify();
}
Javaでwait
メソッドとnotify
メソッドまたはnotifyAll
メソッドを使用する場合、次のことに注意する必要があります。
notifyAll
の代わりにnotify
を使用します。wait
およびnotify
メソッドは、同期されたコンテキストで呼び出す必要があります 。より詳細な説明については、リンクを参照してください。wait()
メソッドを呼び出しますまたは処理を開始できます。wait()
およびnotify()
メソッドの呼び出しに同じオブジェクトを使用します。すべてのオブジェクトには独自のロックがあるため、オブジェクトAでwait()
を呼び出し、オブジェクトBでnotify()
を呼び出しても意味がありません。あなたはこれをまったくスレッド化する必要がありますか?私はあなたの行列がどれほど大きいか、そして一方のスレッドが乗算を実行している間にもう一方のスレッドを印刷することに利点があるかどうか疑問に思っています。
おそらく、比較的複雑なスレッド化作業を行う前に、この時間を測定する価値があるでしょうか?
スレッド化する必要がある場合は、「n」スレッドを作成してセルの乗算を実行し(おそらく「n」は使用可能なコアの数です)、 ExecutorService を使用します Future 複数の乗算を同時にディスパッチするメカニズム。
そうすれば、コアの数に基づいて作業を最適化でき、より高いレベルのJavaスレッドツールを使用しています(これにより作業が楽になります)。結果を受信マトリックスに書き戻し、すべてのFutureタスクが完了したらこれを単に印刷します。
メソッドdoSomething();
を持つBlackBoxClass
という名前のクラスを持つ「ブラックボックス」アプリケーションがあるとします。
さらに、onResponse(String resp)
という名前のオブザーバーまたはリスナーがあり、不明な時間の後にBlackBoxClass
によって呼び出されます。
フローは簡単です:
private String mResponse = null;
...
BlackBoxClass bbc = new BlackBoxClass();
bbc.doSomething();
...
@override
public void onResponse(String resp){
mResponse = resp;
}
BlackBoxClass
で何が起こっているのかわからず、いつ答えが得られるのかわからないが、答えを得るまで、または他のWordでonResponse
を呼び出すまで、コードを継続したくないとしましょう。 「ヘルパーの同期」と入力します。
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();
}
}
モニターを所有するオブジェクトでのみnotifyを呼び出すことができます。のようなものが必要です
synchronized(threadObject)
{
threadObject.notify();
}
notify()
も同期する必要があります
Javaでwait
およびnotify
を使用する正しい方法を示す簡単な例を示します。そこで、ThreadA&ThreadBという名前の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
}
}
}
代わりにスレッドを実行する方法が必要な場合は簡単に使用できます:-
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
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();
}
この特定の問題では、さまざまな結果を変数に保存して、スレッドの最後が処理されたときに、希望する形式で印刷できます。これは、他のプロジェクトで作業履歴を使用する場合に特に便利です。
wait()
を使用してsynchronized(this)
メソッドを呼び出すときに、コードブロックを適切に保護しました。
ただし、保護されたブロックを使用せずにnotify()
メソッドを呼び出す場合、同じ予防策を講じていません:synchronized(this)
またはsynchronized(someObject)
wait()
、notify()
、notifyAll()
メソッドを含む Object クラスのOracleドキュメントページを参照すると、これら3つのメソッドすべてで以下の予防措置を確認できます。
このメソッドは、このオブジェクトのモニターの所有者であるスレッドによってのみ呼び出される必要があります
過去7年間で多くのことが変更されました。SEの質問の下でsynchronized
に代わる他の方法を見てみましょう。
これは、生産者と消費者のパターンの状況のように見えます。 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