4

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

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

我写的代码是这样的:

  1. doGet不同步

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

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

  4. 调用同步函数进行线程计数和文件打印

我正在使用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));
            }

如果您必须到这里,那么感谢您阅读我的问题,如果您对解决问题有任何想法,请提前感谢!

4

3 回答 3

4

我没有看你的代码,但我发现你的方法很复杂。试试这个:

  1. 为要处理的数据创建一个BlockingQueue
  2. 在 servlet 中,将数据放入队列并返回。
  3. 在启动时创建一个工作线程,该线程以 60 秒的超时时间从队列中提取数据并将它们收集到一个列表中。
  4. 如果列表有足够的元素或发生超时,则写入一个新文件。

在 a 中创建线程和队列ServletContextListener。中断线程以停止它。在线程中,当您收到InterruptedException等待队列的时间时,将最后剩余的项目刷新到文件中。

于 2013-07-26T11:37:12.767 回答
1

据我了解,您想在两种情况下创建/生成一个新文件:

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

我建议如下:

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

我试图阅读您的代码,但缺少很多信息,因此请提供更多详细信息:

1)缩进搞砸了,我不确定你复制代码时是否引入了一些错误。

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

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

4) 我不确定我们是否掌握了有关 fileHasBeenPrinted 的所有信息。而且它似乎是一个布尔值,它不是线程安全的。

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

编辑

如果您复制的代码是同步方法,这意味着如果您有很多请求,那么其中只有一个只会在给定时间运行。似乎总是调用 60 秒等待(缩进不是很清楚,但我认为无论文件是否写入,总有 60 秒等待)。因此,您将同步方法锁定 60 秒,然后才能处理另一个线程(请求)。这可以解释为什么您在 20 个请求后不写入文件,因为超过 20 个请求可以在 60 秒内到达。

于 2013-07-26T12:47:33.983 回答