【问题标题】:Should i really care about the thread safe issue in servlet Action class我真的应该关心 servlet Action 类中的线程安全问题吗
【发布时间】:2011-12-31 22:05:02
【问题描述】:

一个 servlet 类处理传入的请求对象,获取数据并存储到 StringBuilder/StringBuffer 并将数据传递给另一个类以写入文件。

ActionClass
    public void doPost(HttpServletRequest request,HttpServletResponse response)
   throws ServletException,IOException {
        String fileName = request.getparameter("fileName");
        String body = request.getParameter("innerHTML");
        String head = request.getParameter("headContents");

        StringBuilder sbr = new StringBuilder();
        sbr.append(body);  sbr.append(head);
                        OR
        StringBuffer sbf = new StringBuffer();
         sbf.append(body);  sbf.append(head);

   FileWrite fw = new FileWrite(fileName, sbf/sbr); /* write the data into file*/
          }

文件写入

    class FileWrite{
       public FileWrite(String fileName, StringBuilder sbf){
        boolean isExist = checkFileName(fileName);  /* return true or false */
         if(isExist){
           String name =  reName(fileName);  /* rename & return new name */
                 /* write the file in new file */
          }else{  /* write in same file name */  }
      }

   public String reName(String oldName){
             /* rename oldName as newName & checks via isExist(newName) */
            } 

   public boolean isExist(String filename) {
         // checks the file in directory, if found already
       return true;
           else return false;
         }
    }

正如您在上面的示例中看到的,动作类将数据传递给FileWrite class,后者将数据写入新文件。可能有数百个客户端同时发送请求以将数据存储在新文件中。
所以我的问题是,在 servlet 类中我应该使用什么来存储数据。String or stringBuffer or StringBuilder??是线程安全的问题吗?

【问题讨论】:

  • 我建议您展示您将代码放入的方法,这样我们就不必做出假设(根据 Neil 关于 doGet 或 doPost 的评论)
  • @Nathan:我也修改并编写了其他类和方法。不管我不确定FileWrite class or it's method 是否需要线程安全,但我希望你现在能明白我的意思。再次感谢

标签: java multithreading servlets thread-safety


【解决方案1】:

是的,您应该关心线程安全问题,但线程安全问题不在于您选择 String 或 stringBuffer 或 StringBuilder。

您需要(可能)注意线程安全的地方是,如果您收到两个对 FileWriter 类的相同文件名的请求。

另外,我要指出,从安全角度来看,直接从 get 参数获取原始文件位置是非常危险的——因为用户可以覆盖其他用户文件,或者(可能取决于权限)甚至操作系统文件。

【讨论】:

  • 非常出色的答案。是的,文件名可能被覆盖,但我有另一个应用程序检查现有文件名,如果文件名相同,则重命名文件并通知客户端。
  • Nathan,正如你所说,我强烈认为FileWriter class 中一定存在线程安全问题,因此确保方法线程安全的正确方法是什么。 static synchronized method() or synchronized method
【解决方案2】:

只要它发生在您的 servlet 的 doGet 或 doPost 中,那么您只处理一个线程。因此,不需要线程安全,这意味着您应该使用比 StringBuffer 更快的 StringBuilder。

【讨论】:

  • 我认为你的意思是“不需要线程安全”而不是“不需要类型安全”
  • 太好了,我也在想同样的事情,但我没有那么自信,也无法在谷歌上找到答案。非常感谢。
【解决方案3】:

对于每个新请求,都会生成一个新的 servlet 线程,它有自己正确包装的唯一上下文。所以 doPost doGet 中的数据保存在该上下文中,因此不受其他请求的影响。

就 String 与 StringBuffer 与 StringBuilder 而言,由于上下文本身是线程安全的,因此不存在同步问题,因此您可以使用 springbuilder。

附带说明:如果不会发生任何变化,为什么不使用简单的字符串??

顺便说一句..注意两个请求来自同一个文件!

【讨论】:

  • 是的,我想只使用 String,但对线程安全的恐惧迫使我考虑 StringBuffer Vs StringBuilder。这就是为什么我刚刚问了这个问题。非常感谢 Nikunj
【解决方案4】:

来自 Java 文档。

StringBuilder 的实例对于多线程使用是不安全的。如果需要这种同步,那么建议使用 StringBuffer。

http://download.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html

首先字符串被内化了。

http://download.oracle.com/javase/1,5.0/docs/api/java/lang/String.html#intern()

这意味着如果您有相同的字符串,这不是问题。

如果您的页眉和页脚是静态的,则它可能位于静态变量中。

【讨论】:

    【解决方案5】:

    如果你在一个方法中声明变量,它将被放置在一个地方调用线程堆栈,只有当前线程可以访问。所以你不必担心线程安全,只要它是一个局部变量 在您的情况下,您应该使用 StringBuider 因为它更快,无需担心这里的线程安全

    【讨论】:

      【解决方案6】:

      您的编码器是线程安全的,这在多线程环境中没有问题。因为您的 ServleClass 没有 Class 级别或 Instance 级别的变量,您的 FileWrite 在 post 方法中是 Instance 。 erver 请求将有一个新的 FileWrite..

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-08-19
        • 1970-01-01
        • 2011-07-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多