长轮询在服务器端杀死线程

时间:2015-03-30 06:40:47

标签: java spring java-ee

早上好/晚上好,

我正在通过ajax-java实现客户端 - 服务器之间的长池化。并且长轮询在客户端正常工作,并且每30秒抛出一个新连接,并且前一个连接被中止。但问题是,在服务器端,所有这些请求/线程都保持活动状态,直到我们有东西返回客户端。但就像我说客户可能不再听了。这里有一些代码:

客户端:

     // Long Polling (Recommened Technique - Creates An Open  Connection To Server ∴ Fast)
  (function poll(){
    var tenantName = $("#tenantName").val();
    $.ajax({
    method:"GET",
    url: "url",
    success: function(data){
        if (data === true) {
            bootbox.alert("Page has been modify <a href='javascript:void(0)' onclick='reload()'>reload</a>");
        }
     }, dataType: "json", complete: poll, timeout: 60000 });
})();

服务器:

       /**
 * @return
 */
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public Boolean getSubStepStatus(@RequestParam("subStep") String subStep,
                                @RequestParam("tenantId") String tenantId) {
    if (!isInStep(subStep, tenantId)) {
        tenantsInStep.get(subStep).add(tenantId);
    }
    while (true) {
        String modifierTenantId = stepModifyByTenant.get(subStep);
        if (modifierTenantId != null && !modifierTenantId.equals(tenantId) && !isInStep(subStep, tenantId)) {
            tenantsInStep.get(subStep).remove(tenantId);
            return true;
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

问题就像我说的那样,所有线程每30秒在服务器端增长和增长,使用这种技术我做错了什么?

2 个答案:

答案 0 :(得分:2)

Thread.sleep(1000);

不是在Java中进行长轮询的方法。这样做的方法是将请求置于异步模式,注册一个监听器,并放弃工作线程。

答案 1 :(得分:0)

您似乎在使用SpringMVC,我认为Web应用程序在servlet引擎(例如Tomcat或Jetty)中运行。

处理请求时,服务器无法检测客户端是否仍在侦听,除非它尝试发送响应数据(see also this question)。您的控制器代码执行可能无限循环(这本身就是一个坏主意)。只要此循环正在运行,就不会发送响应数据,因此即使客户端已断开连接,控制器也将继续循环。

如果你想保持当前的设计,一个简单的解决办法就是防止无限循环,即在经过一定数量的迭代或经过的时间后中断并发送false作为响应。然后客户端必须重新连接才能开始新的轮询周期。