0

私がこのようなクラスを持っていると仮定します:

public class Server {

   public static void main(String[] args) {

      Map<Integer, ServerThread> registry = Collections.synchronizedMap(new LinkedHashMap<Integer, ServerThread>());

      ...

      while(true) {
         Socket socket = serverSocket.accept();
         ServerThread serverThread = new ServerThread(id, registry);
         registry.put(id, serverThread);
      }
   }
}

それで:

public class ServerThread extends Thread {

   private Map<Integer, ServerThread> registry;
   private int id;

   public ServerThread(int id, Map<Integer, ServerThread> registry) {
      this.id = id;
      this.registry = registry;
   }

   ...

   private void notify() {
      synchronized(registry) {
         for(ServerThread serverThread : registry.values()) {
            serverThread.callSomePublicMethodOnThread();
         }
      }      
   }
}

registry繰り返している間、それが変更されないことを確認したいだけです。同期マップにすることで、この動作が保証されますか?synchronizedまたは、ステートメントが必要ですか。同期されたステートメントは、期待どおりに動作しますか?

ありがとう

4

4 に答える 4

5

synchronizedループの周りにブロックが必要です。

詳細については、JavaDocを参照してください。

于 2010-10-08T05:39:20.710 に答える
2

はい、同期されたステートメントは期待どおりに機能します。コメントを1つ追加します。ソケット接続を受け入れているスレッドは、registry.put(id、serverThread);でブロックされます。別のスレッドの同期セクションにいる間。これは、通知を処理している間、サーバーが新しい着信要求を処理しないことを意味します。

putステートメントを(もちろんserverThreadをこれに変更して)ServerThreadのrunメソッドのrunメソッドの最初の行に移動することを検討することをお勧めします。そうすれば、callSomePublicMethodOnThreadの処理に時間がかかっても、着信接続をブロックすることはありません。

于 2010-10-08T06:13:44.610 に答える
1

すべてを簡単にするために、ConcurrentHashMap(http://download.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/ConcurrentHashMap.html)を使用するので、同期ブロックを使用する必要はありません。ループでは、concurrentHashMapは異なるタイプのイテレーター(フェイルファストイテレーターではない)を使用し、concurrentModificationExceptionをスローしないため、パフォーマンスも向上します。

于 2010-10-08T09:57:08.890 に答える
0

コードに1つの問題があります。「notify()」はObjectクラスで定義されたメソッドであるため、メソッドを「private voidnotify()」として定義することはできません。

于 2012-02-28T13:54:49.487 に答える