次の関数は、独自のスレッドで実行されています。
_private void doSendData()
{
try {
//writeToFile(); // just a temporary location of a call
InetAddress serverAddr = InetAddress.getByName(serverAddress);
serverAddr.wait(60000);
//Log.d("TCP", "C: Connecting...");
Socket socket = new Socket(serverAddr, portNumber);
socket.setSoTimeout(3000);
try {
//Log.d("TCP", "C: Sending: '" + message + "'");
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
String message = packData();
out.println(message);
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
connectionAvailable = true;
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
connectionAvailable = false;
} finally {
socket.close();
announceNetworkAvailability(connectionAvailable);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
announceNetworkAvailability(connectionAvailable);
}
}
_
実行がserverAddr.wait(60000)
行に達すると、例外がスローされます。
_Java.lang.IllegalMonitorStateException: object not locked by thread before wait()
_
並行性を防ぐためにオブジェクトまたは関数をロックする方法を知っている人はいますか? Lockオブジェクトを追加しようとしました:
_private final Lock lock = new ReentrantLock();
_
そしてライン
_boolean locked = lock.tryLock();
_
機能の最初でしたが、うまくいきませんでした。
オブジェクトでwait()を呼び出すには、そのオブジェクトの同期ロックを保持する必要があります(ただし、スレッドが待機している間に実際にロックが解除されます)。
synchronized (serverAddr) {
serverAddr.wait();
}
whyこれをやりたいのは、この場合私を困惑させることを認めなければならない...
たぶんあなたが探しているメソッドは Thread.sleep(long) ?このメソッドは、再開する前にミリ秒単位で指定された時間だけwait(スレッドの実行を停止するように)します。
object.wait(long) (これは使用しているものです)はまったく異なることを行います。別のスレッドからの別のオブジェクトに通知するのを待機し(つまり、一種のウェイクアップメッセージを送信する)、指定されたミリ秒数まで待機します。あなたが投稿したコードを考えると、私はこれがあなたが本当に望むものであると非常に疑います。
Thread.sleep()が望んでいない場合は、他の投稿者が述べた同期ブロックを使用する必要があります。
この種のコードを見ると、私はいつもうんざりします。どうぞ、Java.util.concurrent
パッケージをご覧ください。
上記は正しいです。コードの同期ブロックを使用できます。または、ミューテックスと呼ばれるものを作成できます。ミューテックスは、実際には任意のオブジェクトにすることができます。多くの人は、オブジェクト自体をミューテックスとして使用しています。その後、ミューテックスをロックできます。アクセスを取得したいスレッドは、mutexを保持しているスレッドがそれを解放するのを待たなければなりません。
Apocalispによる提案もありました。また、Java.util.concurrentパッケージを確認することをお勧めします。
このエラーメッセージを回避するには、synchronizedキーワードを使用します。
synchronized(serverAddr){
serverAddr.wait(60000);
}
以下のコードが動作するはずです。
private final ReentrantLock lock = new ReentrantLock();
lock.lock(); // block until condition holds
try {
serverAddr.wait(60000);
} finally {
lock.unlock()
}
}
詳細については、このドキュメントを参照してください page .
public void lock()
ロックを取得します。
ロックが別のスレッドによって保持されていない場合、ロックを取得してすぐに戻り、ロック保持カウントを1に設定します。
現在のスレッドがすでにロックを保持している場合、保持カウントは1ずつ増加し、メソッドはすぐに戻ります。
ロックが別のスレッドによって保持されている場合、現在のスレッドはスレッドスケジューリングの目的で無効になり、ロックが取得されるまで休止状態になります。ロックが取得されると、ロック保持カウントが1に設定されます。
lock
に対するsynchronization
の利点については、このSEの質問を参照してください。
一般に、Javaにマルチスレッドプログラムがある場合、同期(キーワード)を使用して共有変数をロックする必要があり、いつでも1つのスレッドのみが共有メモリにアクセスできます。