6

クラスで使用InheritableThreadLocalしています。Servletその子スレッドから利用できるようにします。InheritableThreadLocalスレッドプールエグゼキュータで悪を使用していますか? . サーブレット スレッド プールなど。

私の質問。

InheritableThreadLocals1)サーブレットでの使用を避ける必要があるのはなぜですか?

2) でこのメモリ リークが発生する可能性はありInheritableThreadLocalますか?

3) ? に代わるものはありInheritableThreadLocalますか。

4) スレッドが再利用され、格納されている値threadlocalがクリアされない場合はどうなりますか?

私のリアルタイムシナリオ

public class UserAccessFilter implements javax.servlet.Filter {

      static final InheritableThreadLocal<String> currentRequestURI = new InheritableThreadLocal<String>();

      public void  doFilter(ServletRequest req, ServletResponse resp , FilterChain fc) throws IOException, ServletException{
              String uri = request.getRequestURI();
              fc.doFilter(request, response);         
      }
}


public class MailServlet extends HttpServlet{

      @Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    String mailCount = req.getParameter("mailCount");

    if(mailCount != null && !"".equals(mailCount) && mailCount.matches("[0-9]+")){
        MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount))); //NO I18N
        Thread t = new Thread(mailThread);
        t.start();
    }

    resp.getWriter().println("Mail Servlet.............."); //NO I18N

}              

}

class MailThread implements Runnable{

private String from;
private String to;

public MailThread(String from , String to){
    this.from = from;
    this.to = to;
}


@Override
public void run() {
    sendMail();
}

    public void sendMail(){
        //I want this uri from child threads. I can't pass this value to this constructor.
        String uri = currentRequestURI.get();
        //Do Mail Operations
    }


}

フィルター --> サーブレット A --> 子スレッド ---> メール スレッド (ここでは、フィルターに設定された値を取得しています)。

4

2 に答える 2

15

サーブレットで InheritableThreadLocals を使用しないようにする必要があるのはなぜですか?

これらは、あるリクエストから別のリクエストへの情報漏えいの潜在的な経路を表しています。「問題」は、リクエストがスレッドのプールによって処理されることです。オン リクエストが完了すると、スレッドが処理する次のリクエストは別のユーザーに対するものである可能性が高くなります。ただし、最初のリクエストの終了時にスレッド ローカル状態をクリアするのを忘れると、2 番目のリクエストで使用される可能性があります。

InheritableThreadLocal でメモリ リークが発生する可能性はありますか?

はい...ちょっと。ワーカー プールが制限されていると仮定すると、任意のスレッドのスレッド ローカル状態が上書きされる可能性が高くなり、メモリ リークが解消されます。最悪の場合、問題は限定的なメモリ リークです。プール内のスレッドの数によって限定されます。

それよりも気になるのが情報漏えい問題です。

InheritableThreadLocal に代わるものはありますか?

リクエストまたはレスポンス オブジェクトで属性を設定する方が適切です。

スレッドが再利用される場合、threadlocal に格納されている値はクリアされません。

クリアされません。それが問題だ!

于 2013-01-24T10:20:10.357 に答える
0

あなたの例は機能し、作成時の値をMailThread 継承currentRequestURIします。

しかし、UserAccessFilterと はjava.lang.InheritableThreadLocal、コードが行おうとしていることを混乱させるだけであり、これは悪い部分です。

MailThread次のようにリクエストURIを渡すことができるようにコンストラクタを変更すると何が問題なのですかMailServlet

MailThread mailThread = new MailThread("xxx@gmail.com", generateToAddress(Integer.parseInt(mailCount)), req.getRequestURI());

そうすれば、スレッド ローカルが不要になり、フィルターが不要になり、コードがより明確になります。

于 2013-01-24T10:19:14.850 に答える