小さなトランザクションが多数発生する場合、すなわち、 クライアントとは少量のデータを交換する軽い通信を行うだけだが 大量のクライアントから頻繁に接続要求がある場合、 各クライアントが接続してくる度に新しいスレッドを 生成していては反応が遅れてしまう場合があります。
同時に処理しなければならないクライアントの数があらかじめ 予測できるのであれば、それだけの個数のスレッドを前もって 生成しておくことでこの問題に対処できます
この場合、各クライアントからの要求に対応するサーバスレッドそれぞれが、 クライアントからの接続を受け付けるために自分で ServerSocketを使ってaccept()を実行する必要があります。 しかしServerSocketクラスのaccept()メソッドはスレッドセーフ ではないので、同時に複数のスレッドが同じServerSocketに対して accept()メソッドを実行してしまっては正しく動作しません。 そのため、各スレッドがaccept()する部分で synchronized を指定して、 一度にひとつのスレッドしかaccept()呼び出しができないようにします。 accept()を実行したスレッドはクライアントからの接続があるとaccept()を 終了してsynchronized領域から抜けます。 すると ServerSocketに対するロックが解除されるのを待っていたスレッドが 動作を再開してロックを取るために競争します。運よくロックを取得できた スレッドがsynchronized領域に入ることができてaccept()メソッドを実行します。 ロックを取得できなかったその他のスレッドはふたたびロックが開放されるのを 待ってwait状態になります。
ここではクライアントの世話をするために EchoHandler2という クラス(Runnableをimplementsしている)を作成しています。
RunEchoServerThreaded2.javaの実行例(サーバ) |
|
実行例(クライアント0) |
|
実行例(クライアント1) |
|
実行例(クライアント2) |
|