- PR -

スレッドを使って、別処理をさせたい

投稿者投稿内容
hatsu
会議室デビュー日: 2007/04/09
投稿数: 3
投稿日時: 2007-07-13 18:58
画面を先に表示させ、
スレッドを使って、別処理をさせることを考えています。

その別処理の中でrequestの値を使って処理を行います。
一度目は正常にrequestの値を取ってくるのですが、
二度目以降は値がnullとなってしまいます。

以下に実行させようとしているロジックを抜粋しました。


--呼出元ロジック----------------------
Thread aThread = new Thread(new NewRunnable(aRequest,aResponse));
aThread.start();

//画面表示
getServletContext().getRequestDispatcher("a.jsp").forward( aRequest, aResponse );
-------------------------------------

--NewRunnableクラス------------------
class NewRunnable implements Runnable {

 HttpServletRequest request = null;
 HttpServletResponse response = null;

 public NewRunnable(
HttpServletRequest request,
HttpServletResponse response) {
  this.request = request;
  this.response = response;
 }

 public void run() {
System.out.println("request=" + request );
System.out.println("test=" + request.getParameter("test"));
 }
}
-------------------------------------

上記ロジックで
一回目の実行は
request=*********
test=****
と出力されたのですが、
二回目の実行は
request=*********
test=null
と出力されていまいました。

何が原因なのか検討が付かず、ご教授をお願い致します。
あしゅ
ぬし
会議室デビュー日: 2005/08/05
投稿数: 613
投稿日時: 2007-07-13 19:26
別スレッドで処理を行っている間にリクエストが完了したのでしょう。
完了したリクエストのメソッド呼び出しの結果は未定義だと思います。

スレッドの開始前にリクエストから必要な情報を全て取得するか、
非同期処理が完了するまでリクエストの終了を待機させる必要があります。
朝日奈ありす
大ベテラン
会議室デビュー日: 2007/05/02
投稿数: 189
お住まい・勤務地: 最北の地
投稿日時: 2007-07-13 20:38
Stream上のオブジェクトなので getParameter(KEY)は一度読み込むとそれ以後 null を返したような記憶があります。
request#setAttribute( KEY, request#getParameter(KEY)
とし、request#getAttribute(KEY)を使用するようにすればいけるはずです。

getParameterMap

java.util.Map getParameterMap()

このリクエストから取得できるパラメータを java.util.Map で返します。 リクエストパラメータというのはリクエストに付けられて送られてくる付加情報です。 HTTP Servlet ではパラメータはクエリー文字列になっているか、あるいは、フォームデータ形式でポストされます。

戻り値:
パラメータ名が key 、パラメータ値がマップの値と なっている不変な java.util.Map。 パラメータマップの key は String 型。 パラメータマップの値は String の配列です。

というメソッドも Parameterだけの処理ならつかえそうですね。
mio
ぬし
会議室デビュー日: 2005/08/25
投稿数: 734
お住まい・勤務地: 神奈川県
投稿日時: 2007-07-13 20:46
final Stringに値を受けておいたらよかったような。
かつのり
ぬし
会議室デビュー日: 2004/03/18
投稿数: 2015
お住まい・勤務地: 札幌
投稿日時: 2007-07-14 00:49
リクエストオブジェクトもレスポンスオブジェクトも、
APサーバのHTTPの低レベルなやり取りに対する、単なるプレースホルダに過ぎません。
したがって、HTTPの通信が完了した段階で用済みのオブジェクトとなります。

解決法としては一通り情報が出ていますが、
一旦リクエストというスコープからリクエストが生きている間に、
外のスコープに出す必要があります。

>杏さん
リクエストが生きている間は何度でも読み取れますよ。
hatsu
会議室デビュー日: 2007/04/09
投稿数: 3
投稿日時: 2007-07-16 12:21
皆様、ご教授ありがとうございました。
大変勉強になりました。

リクエストが完了したので、値が取れなかったのですね。
スレッドに渡る前に、一度リクエストから必要な値をとって
処理を実行させてみることにします。

結果はまたお伝えしたいと思います。

ありがとうございました。
nagise
ぬし
会議室デビュー日: 2006/05/19
投稿数: 1141
投稿日時: 2007-07-16 12:36
Servletで別スレッドを使う場合、スレッドの処理とHTTPのやり取りをよく設計しておく必要があります。
というのも、HTTPはリクエストに返してレスポンスするという単純なやりとりしかできないので、スレッドを立てて終わったら通知しようとすると(特殊なことをしない限り)無理なのですね。
HttpResponseオブジェクトへの参照をずっと保持していても、結局、HTTPのレスポンスが終わったあとでは送信できません。
そのため、ブラウザとの間でどういう通信をさせるか、かなり悩むことになります。

たまに挙る要件ですが、集計処理などの思い処理をサーバでやる場合に、別スレッドで処理しつつ、画面には途中経過を表示する、ということをやろうとしたら結構複雑なスレッド制御が必要になってきます。

レスポンスを返したければ、まずはブラウザからリクエストさせなければならない…。
今回の問題が、単に値を読めないだけの話なら、スレッドを立てる時点で読むだけ呼んでオブジェクトに格納してスレッドに渡すだけでよいのですが、提示のソースではレスポンスオブジェクトもスレッドに渡していますよね?
スレッド側からはレスポンスできないので気をつけてください。
hatsu
会議室デビュー日: 2007/04/09
投稿数: 3
投稿日時: 2007-07-17 12:09
requestで取得している値を調べ直し、必要な値だけ引数にセットしてスレッドを実行させることにしました。
この方法で問題なく実行できました。
皆様、ありがとうございました。

>nagiseさん
指摘を受け、レスポンスについても調べました。
今回はレスポンスオブジェクトを使った作業はないと判明し、結果的に値の問題だけで解決しました。
ご指摘ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)