2009-09-10 20 views
5

私のアプリに自宅のWebサーバーがあります。このWebサーバーは、ソケットに入ってくるすべての要求に対して新しいスレッドを生成します。私は、Webサーバが、作成したばかりのスレッドで特定のポイントに達するまで待つ必要があります。Java用スレッドの同期

私は、このサイトとWeb上の例で多くの記事を読んできましたが、スレッドに待つように指示してからWebサーバーを起動できません。基本的なコード例は素晴らしいでしょう。

synchronizedキーワードはこれについて正しい方法ですか?もしそうなら、これはどのように達成できますか?コード例は、私のアプリの下にある:

Webサーバー

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だけで(もちろん、別のクラスとしてインターフェイスとHttpRequestaddResumeListener(ResumeListener r1)メソッドを追加)resumeListener.resume()を呼び出しん:

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

ちょうど学術疑問として、なぜあなたはあなた自身のウェブサーバーのコードを書くのですか? – MattC

+0

アプリは暗号化されたコンテンツを表示するので、基本的に自分の内部Webサーバーを作成して認証を実行できます。外部のブラウザがデータを通過させている同じソケットを使用しようとすると、要求が私のアプリケーションから来た場合、内部的に提供する適切な資格情報を持っていないでしょう。 – Ken

+0

これは、他のWebサーバーを使用することをどのように妨げているのかわかりません。ほとんどのWebサーバーは、IPベースの認証をサポートしています。 – bdonlan

答えて

1

まず、私はここで車輪を再発明することで、あなたのためにさまざまな問題につながる可能性が高いと他人の感情をエコーし​​ます。しかし、あなたがやっていることをとにかくこの道を歩きたいのであれば、難しいことではありません。あなたは桟橋で実験しましたか?

たぶん、このような何か:

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; 
    } 
} 
+0

ありがとうございます。それはかなりまっすぐ進むように思われ、私はそれも試してみましょう。私は自分のWebサーバを実装することの懸念を理解しています。私はすでにJettyを簡単に見てきましたが、進んでいませんでした。桟橋はまだ未来の可能性がありますが、現在では家庭の整備は順調です。 – Ken

7

これのために1のカウントを有するjava.util.concurrent.CountDownLatch。そのインスタンスが作成され、親スレッドと子スレッドによって共有されるように調整します(たとえば、HttpRequestのコンストラクターで作成し、メンバー関数によって取得可能にします)。その後、サーバはawait()を呼び出し、そのスレッドは親を解放する準備ができたらcountDown()に達する。

+0

提案してくれてありがとう、私はこの方法を実装しようとします。シンプルだと思われる。 – Ken

3

おそらくJava Conditionを使用する必要があります。ドキュメントから:

条件(も条件として知られている キューや条件変数)他のスレッドによって通知さ まで(「待つ」へ) 実行を中断するために、1つのスレッドのため 手段を提供するいくつかの状態 条件今は真実かもしれない。

+1

条件変数だけではオープンコードが少し難しいです。ループとブロックをいつ停止するかを知るために、関連するロックとフラグも必要です。さらに、Conditionクラスを直接使用する必要はありません。すべてのオブジェクトで暗黙のうちにモニタを使用してください... – bdonlan

+0

また、明示的なシステムのためのコンディション/ロックmakeを少し明確にするために、 'synchronized'と' Object.wait 'によって使用されるビルトインモニタとは独立したもの() 'を返します。単一のロックに複数の条件変数を追加する必要がある場合に便利ですが、この場合は過剰です。 – bdonlan

+0

実際には、 'Condition'はインターフェースです。実際には実装クラスを使用する必要があるため、私はそれを指摘していました。リンク先のページには、ReentrantLockの例があります。 –

-3

デバッガの下で実行すると、ブレークポイントを設定しますか?

実行できない場合は、System.inから行を読み込みますか?

+0

これがどのように質問に関係しているのか分かりません.... –