- ベストアンサー
サーブレットのスレッド管理について
はじめまして、現在Web Developperを目指し日々サーブレット,JSP, JavaBeansの勉強を続けております。お聞きしたいことは、サーブレット, JavaBeansのスレッド管理です。個人で勉強していると多数のクライアントが一つのサーバーにアクセスするなどという 環境をつくりずらいので、業務経験のあるかたからアドバイスをいただきたいです。 現在スレッドを管理する方法とて,SingleThreadModel インターフェイスの実装かsyncronizedコードを利用できることを知っております。 質問1. 実際のシステムで使われているスレッド管理もこの二つの方法で行われているのでしょうか? 質問2. JDBCよりデータベースに書きこむ部分は、二つのスレッドが同時にDBのデータを書き込まないように、shncronizedコードで囲まなくてはいけないと学びましたが、他の本でDBにはすでに同時アクセス を防ぐ仕組みがあるから、synchronizedコードを書かなくてもよいとかいてありました。どちらが正しいのでしょうか? 質問3. 業務のスレッド管理で主に気をつけなければいけないところは、DBとローカル変数がスレッドセーフになっていることでしょうか、他にも注意するべき点がありますでしょうか? 初心者の質問ですので、的を得ていないところが多々あると思います。それでも少しでも、技術者の方に近づければと思い質問させていただきました。もしよろしければご教授よろしくお願いいたします。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
>JavaBeansのインスタンスのことをいっていますか?メモリは消費しても、リクエストごとに違うインスタンスを作成したほうがよいということでしょうか? JavaBeansの事です。正確には、何のクラスでも良いのですがapplicationスコープに居座ったり、staticな変数で参照され続ける(結果的に終了までメモリにいる)データというのは、最小限にすべきだという事です。 リクエスト毎に生成すべきか?という質問は、基本的にYESです。 複数リクエストで共有したいデータの場合、sessionスコープに持たせて下さい。それ以外の使い捨てデータは、毎回生成が基本です。 application, session, requestのスコープの違いは、Servlet本に書いてあるはずです。
その他の回答 (5)
- choconamacream
- ベストアンサー率44% (152/338)
私の方からも、ちょこっとだけ補足を・・・。 (1)「二つのスレッドが同時にDBのデータを書き込まないように、shncronizedコードで囲まなくてはいけない」と書かれている本 →すんごい古い本のように思われます。一応、どのような実装になっているかは、以下のサイトにて理解できるかと思いますが、あくまで参考程度に。 [コネクションプーリングを自作クラスにて実現] http://www.hellohiro.com/jspdb.htm (2)「すでに同時アクセスを防ぐ仕組みがあるから、synchronizedコードを書かなくてもよい」と書かれている本 →いわゆる、データソースを使用したものですね。j2sdk1.4より使用できます。こちらも、以下にServletとserver.xmlにて実装されているサイトを載せておきます。Strutsでも同じような感じですね。 [コネクションプーリングをjavax.sql.DataSourceにて実現]] http://www.hellohiro.com/datasource.htm #4さんと同じく、基本的にサーブレットやJSPを扱うWeb開発下では、スレッドがらみのものは全て、サーブレットコンテナがやってくれているので、それほど気にする必要も無いように思います。実際には、スレッドにライフサイクルがあるのと同じように、サーブレットにも似たようなライフサイクルがありますよね。(終了処理など、厳密には違う部分もいくつかありますが・・。)
- dekopa-
- ベストアンサー率42% (161/378)
>このスレッドの再利用というのは、業務においてはほとんどのシステムで使われているのでしょうか。 使われています。というか、サーバー製品で勝手に実装済みなので、開発者が意識することはあまりありません。 >また多数のスレッドからアクセスされるようなインスタンスを作ることはなぜよくないのでしょうか? 複数スレッドからアクセスされるインスタンスは、synchronizedで排他処理しなければいけないからです。排他処理は、バグの温床です。 マルチスレッド下で発生するバグは、再現しづらく、なかなかバグが取れません。ある処理を実行中、別のスレッドから値を書き換えられてバグが発生する、その「あるタイミング」を再現するのがどんなに困難か想像できますか? Eclipse等で、デバッグすることも出来ません。なにせ「ブレークポイントでストップ」させた瞬間、タイミングはずれてしまうのですから。 最善なのは、正しく排他処理をおこなうJavaコードを書くことではなく、そもそもそんな排他処理が必要なマルチスレッドコードを書かないことです。 そしてServletの処理の大半は、マルチスレッドなんて必要としません。サーバーがマルチスレッドで動いているのは複数のリクエストを同時処理する為ですが、1つのリクエストは1つのスレッドですから、プログラマはマルチスレッドを意識しません。 ところが、メモリ上にいつまでも居座って複数スレッドから参照されるようなインスタンスを使うと、途端にこの前提がくずれ、バグの温床になります。 問題を切り分けて下さい。 Servletプログラミングを知りたいなら、スレッドを意識する必要はありません。 マルチスレッドプログラミングを知りたいなら、Servletとは切り離して勉強して下さい。
- umepapa05
- ベストアンサー率0% (0/1)
No.2さんが丁寧に回答されてるようなので 補足の情報として書かせていただきます。 質問を読ませていただいてる限りでは、マルチスレッドの長所・短所を勉強するのが一番良いのではないかと思います。synchronizedにしなければいけない意味がわかると理解が深まると思います。 No.2さんも書かれてますが、実際の業務では多数のアクセスがあることが多いので、SingleThreadModelではハンドリングしきれません。そこで、マルチスレッドにして複数の接続オブジェクトを生成することが多いです。 Servletに関連した業務で直接的にスレッド管理をすることはあまりないと思いますが、Servlet自身のスレッド管理に対しての話の場合は、tomcatとかjavaで書かれたウェブサーバのソースを参考にすると良いと思います。 http://jakarta.apache.org/ 一番いいのは自分で経験するのがベストだと思います。プロでも本番環境に移行するまでは、生のアクセスを経験することはできません。ですので、以下のようなフリーのソースを使ってテストしてますよ。 http://www.microsoft.com/japan/technet/archive/itsolutions/intranet/downloads/webstres.mspx では、頑張ってください
補足
フリーのソースの場所まで教えていただき感謝いたします。 >マルチスレッドにして複数の接続オブジェクトを生成 >することが多いです 同じJavaBeansクラスを使うとしても、違うインスタンスをそれぞれのリクエストに割り当てろということでしょうか?また >Servletに関連した業務で直接的にスレッド管理をす >ることはあまりない との事なのですが、Strutsにはスレッド管理を自動でプログラムしてくれる機能がすでにそなわっているのでしょうか?
- dekopa-
- ベストアンサー率42% (161/378)
まず、今直接Servletを業務で書く場面は殆どありません。 Strutsか、それを拡張したモノか、類似のフレームワークを使うのが殆どです。Servletの知識も無駄ではありませんが、さらっと流して先に進む事をお勧めします。 1.SingleThreadModelは使いません。制御しないか、せいぜいsynchronizedだけです。 2.DB側で排他処理をしていますので、呼び出し側は何もしません。後者が正解です。 3.あまり多数のスレッドからアクセスされるようなインスタンスを作らない事です。通常は、長く持ちたいデータはセッション上に持てば十分です。 セッションは、通常複数のリクエストで共有されますが、スレッドはリクエスト毎に違います。 さらに、スレッドは再利用されます。「スレッドプール」で調べてみて下さい。 全く関係のないリクエスト間でスレッドが共有される可能性があるので、スレッドのインスタンスに値を保存してはいけません。
補足
>「スレッドプール」で調べてみて下さい。 これは私の知らなかった方法なのですが、このスレッドの再利用というのは、業務においてはほとんどのシステムで使われているのでしょうか。また多数のスレッドからアクセスされるようなインスタンスを作ることはなぜよくないのでしょうか?それぞれのクライアントに同じクラスの別々のインスタンスを割り当てるべきだということでしょうか?
1.実際のシステムでシングルスレッドにすることはまずありえません。 2.DBに対する書き込みの排他はDBの排他機能を使うので、わざわざ同期化することはありません。 3.ローカル変数が競合を起こすことはありません。 気をつけることは、サーブレットのインスタンス変数を使わない。 やたらにstaticにしない。 くらいでしょうか。
補足
丁寧なご解答ありがとうございました。非常にわかりやすい説明で、業務の経験からくる知恵を少し分けてもらった気がします。 >メモリ上にいつまでも居座って複数スレッドから参照されるようなインスタンス サーブレットはいつまでもメモリ上に居座らざるおえないと思うので、これはJavaBeansのインスタンスのことをいっていますか?メモリは消費しても、リクエストごとに違うインスタンスを作成したほうがよいということでしょうか?(同じJavaBeans クラスを使う場合でも) 長々と説明してしまってもうしわけありません。この質問が終わりましたら、ポイントを差し上げるつもりですので、最後にこれを教えていただけませんか?