Java のスレッドでの同期
-
05-07-2019 - |
質問
私のアプリには自家製のWebサーバーがあります。この Web サーバーは、ソケットに入って受け入れられるリクエストごとに新しいスレッドを生成します。Web サーバーには、作成したばかりのスレッド内で特定のポイントがヒットするまで待機してもらいたいと考えています。
このサイトの多くの投稿や Web 上の例を調べてきましたが、スレッドに待機するように指示した後、Web サーバーを続行させることができません。基本的なコード例は素晴らしいでしょう。
synchronized キーワードはこれを解決する正しい方法ですか?もしそうなら、どうすればこれを達成できるでしょうか?私のアプリのコード例は以下のとおりです。
ウェブサーバー
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.run();
///////////////////////////////
wait here until notifed to proceed
///////////////////////////////
} catch (Exception e) {
e.printStackTrace(logFile);
}
}
スレッドコード
public void run() {
//code here
//notify web server to continue here
}
更新 - 最終的なコードは次のとおりです。の HttpRequest
電話するだけです resumeListener.resume()
応答ヘッダーを送信するたびに (もちろん、インターフェースを別のクラスとして追加し、 addResumeListener(ResumeListener r1)
のメソッド HttpRequest
):
Webサーバー部分
// server infinite loop
while (true) {
//block here until a connection request is made
socket = server_socket.accept();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
HttpRequest request = new HttpRequest(socket, this);
request.addResumeListener(new ResumeListener() {
public void resume() {
//get control of the lock and release the server
synchronized(locker) {
locker.notify();
}
}
});
synchronized(locker) {
//create a new thread for each request
Thread thread = new Thread(request);
//run the thread and have it return after complete
thread.start();
//tell this thread to wait until HttpRequest releases
//the server
locker.wait();
}
} catch (Exception e) {
e.printStackTrace(Session.logFile);
}
}
解決
まず最初に、ここで車輪の再発明を行うと、さまざまな問題が発生する可能性が高いという他の人の意見に私も同意します。しかし、とにかくこの道を進みたいのであれば、やろうとしていることは難しいことではありません。Jetty を試してみたことがありますか?
おそらく次のようなものでしょう:
public class MyWebServer {
public void foo() throws IOException {
while (true) {
//block here until a connection request is made
ServerSocket socket = new ServerSocket();
try {
final Object locker = new Object();
//create a new HTTPRequest object for every file request
MyRequest request = new MyRequest(socket);
request.addResumeListener(new ResumeListener() {
public void resume() {
locker.notify();
}
});
synchronized(locker){
//create a new thread for each request
Thread thread = new Thread(request);
//start() the thread - not run()
thread.start();
//this thread will block until the MyRequest run method calls resume
locker.wait();
}
} catch (Exception e) {
}
}
}
}
public interface ResumeListener {
public void resume();
}
public class MyRequest implements Runnable{
private ResumeListener resumeListener;
public MyRequest(ServerSocket socket) {
}
public void run() {
// do something
resumeListener.resume(); //notify server to continue accepting next request
}
public void addResumeListener(ResumeListener rl) {
this.resumeListener = rl;
}
}
他のヒント
java.util.concurrentを使用できます。 .CountDownLatch の場合、カウントは1です。インスタンスを作成して、親スレッドと子スレッドで共有するようにします(たとえば、 HttpRequest
のコンストラクターで作成し、メンバー関数で取得できるようにします)。次にサーバーは await()
を呼び出し、親を解放する準備ができるとスレッドは countDown()
をヒットします。
おそらくJavaを使用する必要があります条件。ドキュメントから:
条件(条件とも呼ばれる キューまたは条件変数)提供 1つのスレッドが中断するための手段 通知されるまで実行(「待機」) ある状態の別のスレッドによって 条件が真になる可能性があります。
デバッガーで実行し、ブレークポイントを設定しますか?
実行不可能な場合は、System.inから行を読みます