具有多线程的Java Servlet

时间:2013-07-26 11:16:33

标签: java multithreading servlets

我正在尝试根据servlet请求中的数据创建多个输出文本数据文件。我的servlet的约束是:

  • 我的servlet在生成文件之前等待足够的请求达到阈值(例如文件中的20个名称)
  • 否则会在一分钟后超时并生成文件

我写的代码是这样的:

  1. doGet未同步

  2. doGet内我正在创建一个新的线程池(原因是我的servlet的调用应用程序在我的servlet返回响应之前不会发送下一个请求 - 所以我验证了请求并返回立即确认回来获取新请求)

  3. 将所有请求数据传递给在新线程池中创建的线程

  4. 调用同步函数进行线程计数和文件打印
  5. 我正在使用wait(60000)。问题是代码在一分钟内生成具有正确阈值(名称)的文件,但是在一分钟超时之后,生成的文件(极少数)超出了容量,例如,名称超过了我在容量。

    我认为它与线程有什么关系,当它们醒来时会引起问题?

    我的代码是

    if(!hashmap_dob.containsKey(key)){
    request_count=0;
    hashmap_count.put(key, Integer.toString(request_count));
    
    sb1 = new StringBuilder();
    sb2 = new StringBuilder();
    sb3 = new StringBuilder();
    
    hashmap_dob.put(key, sb1);
    hashmap_firstname.put(key, sb2);    
    hashmap_surname.put(key, sb3);
                    }
    
    if(hashmap_dob.containsKey(key)){
        request_count = Integer.parseInt(hm_count.get(key));
        request_count++;
        hashmap_count.put(key, Integer.toString(request_count));
        hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));  
                    }
    
    
              hashmap_dob.get(key).append(dateofbirth + "-");
        hashmap_firstname.get(key).append(firstName + "-");
        hashmap_surname.get(key).append(surname + "-");
    
    
        if (hashmap_count.get(key).equals(capacity)){
    
            request_count = 0; 
    
        dob = hashmap_dob.get(key).toString();
        firstname = hashmap_firstname.get(key).toString();
        surname = hashmap_surname.get(key).toString();
    
        produceFile(required String parameters for file printing);
    
        fileHasBeenPrinted = true;
        sb1 = new StringBuilder();
        sb2 = new StringBuilder();
        sb3 = new StringBuilder();
    
        hashmap_dob.put(key, sb1);
        hashmap_firstname.put(key, sb2);
        hashmap_surname.put(key, sb3);
        hashmap_count.put(key, Integer.toString(request_count));
        hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));
                }
        try{
    
        wait(Long.parseLong(listenerWaitingTime)); 
    
    
            }catch (InterruptedException ie){
                System.out.println("Thread interrupted from wait");
                }
    
        if(hashmap_filehasbeenprinted.get(key).equals("false")){
    
        dob = hashmap_dob.get(key).toString();
        firstname = hashmap_firstname.get(key).toString();
        surname = hm_surname.get(key).toString();
    
        produceFile(required String parameters for file printing );
    
        sb1 = new StringBuilder();  
        sb2 = new StringBuilder();
        sb3 = new StringBuilder();
        hashmap_dob.put(key, sb1);
        hashmap_firstname.put(key, sb2);
        hashmap_surname.put(key, sb3);
        fileHasBeenPrinted= true;
        request_count =0;
        hashmap_filehasbeenprinted.put(key, Boolean.toString(fileHasBeenPrinted));
    
        hashmap_count.put(key, Integer.toString(request_count));
                }
    

    如果你必须到这里,那么感谢你阅读我的问题并提前感谢你是否有任何想要解决的问题!

3 个答案:

答案 0 :(得分:4)

我没有查看您的代码,但我发现您的方法非常复杂。试试这个:

  1. 为要处理的数据创建BlockingQueue
  2. 在servlet中,将数据放入队列并返回。
  3. 在启动时创建一个工作线程,从队列中提取超时60秒的数据并将其收集到列表中。
  4. 如果列表中有足够的元素或发生超时,请写一个新文件。
  5. ServletContextListener中创建线程和队列。中断线程以阻止它。在线程中,当您在队列中等待时收到InterruptedException时,将最后剩余的项目刷新到文件中。

答案 1 :(得分:1)

根据我的理解,您希望在两种情况下创建/生成新文件:

  • 请求数量达到预定义阈值。
  • 阈值超时完成。

我建议遵循:

  1. 使用APPLICATION-SCOPED变量:包含HttpServletRequest对象的requestMap。
  2. 在每个servlet命中时,只需将收到的请求添加到map中。
  3. 现在创建任何合适的侦听器/过滤器requestMonitor,以监视requestMap的值。
  4. RequestMonitor应检查requestMap是否已增长到预定义的阈值。
  5. 如果没有,则应该允许servlet添加请求对象。
  6. 如果有,那么它应该打印文件,空的requestMap,然后允许Servlet添加下一个请求。
  7. 对于超时,您可以检查在APPLICATION_SCOPE中使用LAST_FILE_PRODUCED变量生成最后一个文件的时间。每次生成文件时都应该更新。

答案 2 :(得分:1)

我试图阅读您的代码,但缺少很多信息,所以如果可以请提供更多详细信息:

1)缩进版本搞砸了,我不确定复制代码时是否有错误。

2)您发布的代码是什么?在doGet之后在其他一些线程上调用的代码?

3)也许你也可以添加变量声明。那些线程安全类型(ConcurrentHashMap)?

4)我不确定我们是否拥有关于fileHasBeenPrinted的所有信息。它似乎也是一个布尔值,它不是线程安全的。

5)你谈论“同步”功能,但你没有包含这些功能。

修改

如果您复制的代码是同步方法,则表示如果您有许多请求,则只有其中一个请求只在给定时间运行。似乎总是调用60秒等待(压痕不太清楚,但我认为总是有60秒等待,无论文件是否写入)。因此,在处理另一个线程(请求)之前,您将同步方法锁定60秒。这可以解释为什么你没有在20个请求之后写文件,因为超过20个请求可以在60秒内到达。