SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

GlassFishからアプローチするJava

GlassFishからアプローチするJava~入門編~
第2回「Webアプリケーションの作成 Servletの基礎を学ぶ」

Servletって何?


クライアントとServletの関係

 Servletを簡単に言ってしまえば、(1)クライアントからリクエストを受け付け、(2)リクエストに応じた処理を行い、(3)クライアントへレスポンスを返すクラスです(非常に簡単そうに聞こえますが、実は基礎を知らないと落とし穴に落ちやすいクラスでもあります)。図2がそれを概念化したものです。

図2.クライアントとServletの関係
図2.クライアントとServletの関係

 Servletはクライアントの受付係です。このように言われても理解できないと思うので、一旦Servletから離れ、次のような状況を考えてみます。

 例えば、Aさんからリクエストを受け付けたらインスタンスAを生成し、Bさんからリクエストを受け付けたらインスタンスBを生成し・・・とクライアントごとにインスタンスを生成するという教科書どおりのオブジェクト指向を利用した方法をとった場合、ちょっとしたWebサイトでもあっという間にメモリリーク(メモリを使い果たし何も処理ができなくなること)を起こしてしまいます。資源が無限にあるとすれば、この方法が1番いい方法と言えるでしょう。ただし、資源が有限だとすれば、1クライアントに1インスタンスを与えていてはメモリがすぐに不足します。

 上記の問題に対処するには、アクセス数の制限をかけるという方法もあります。ただし、制限をかけすぎるとビジネスチャンスを失うことにもなりかねません。また、GoogleやAmazonなどのクラウドを利用することでアクセス数に応じてリソースを柔軟に増減させることで対処することも可能です。どの方法を取るにしろ、メモリを節約するプログラミングをすることが肝要です。

 それでは、メモリを節約する方法を考えましょう。ServletXはクライアントAからリクエストを受け付けたら(図2の1)スレッドAを生成します(図2の2)。スレッドとインスタンスの区別は大切です。インスタンスはそれ自身のメモリ空間が存在します。それに対し、スレッドはそれ自身のメモリ空間を持ちません(スレッドは大きなテーマのため、最後に参考文献を挙げています)。そのスレッドAがクライアントAの要求に応えます。再度クライアントAからServletXに対し要求を出しても(図2の4)実際にはスレッドAがその要求に応えます。これ以降ServletXとクライアントAは直接やりとりしません。クライアントBからリクエストを受け付ければスレッドBを生成する、クライアントCからリクエストを受け付ければスレッドCを生成するというようにしてメモリを節約します。厳密にいえば、リクエストの度にスレッドを生成するのはコストがかかるため、スレッドプールというものをアプリケーションサーバは持っています。リクエストがあればプールから取り出します。

 スレッドを生成させるコードを書く必要はありません。ServletXを普通に呼び出せばスレッドは生成されます。ただし、初めてServletXクラスを呼び出す場合のみインスタンスが生成されます。これは後ほどServletのライフサイクルとして紹介します。実際にスレッドは入門者には難しい概念です。ただし、Webアプリケーションに限れば、以下のことに注意すれば問題を回避できます。

  • 1つのServletから生成されたスレッドはメモリ空間を共有する

 このたった1つの事実を知ることで、多くのバグを予防できるのです。つまり、クライアントAとクライアントBは同じメモリ空間を使用します。これは非常に困ったことになります。

 サンプルプログラムとしてひたすら数字を足すプログラムを考えましょう。クライアントAがXというメモリ領域に100という数値を書き込んでも、その後にクライアントBがXに200という数値を書き込むと最初の100という数値に200が加算され合計が300となってしまいます。この時点でクライアントBはなぜ200ではなく300なのか首を傾げることになります。クライアントAはそれを知らずにXに300を足して合計400にしようとしても、結果は600となってしまいます。つまり、クライアント毎の情報は保持されないということを意味しています。これは由々しきことです。クライアント毎の情報を保持できないのであれば、Webアプリケーションの構築ができなくなってしまうからです。

 それでは、次ページから実際にプログラムを作成し、実験してみましょう。

次のページ
スレッド間のメモリ共有テスト

この記事は参考になりましたか?

GlassFishからアプローチするJava連載記事一覧

もっと読む

この記事の著者

川久保 智晴(カワクボ トモハル)

haruプログラミング教室(https://haru-idea.jp/)主宰。COBOL、FORTRANで13年、Javaを中心としたWeb開発で11年。3つしか言語知らないのかというとそうでもなく、sed/awk、Perl、Python, PHP,  C#, JavaScriptなども一時期は業...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/4748 2010/02/12 11:06

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー