Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 每个访问者只启动一次线程的Servlet_Java_Multithreading_Servlets_Multi User - Fatal编程技术网

Java 每个访问者只启动一次线程的Servlet

Java 每个访问者只启动一次线程的Servlet,java,multithreading,servlets,multi-user,Java,Multithreading,Servlets,Multi User,嘿,我想实现一个Javaservlet,它只为每个用户启动一次线程。即使在刷新时,也不应再次启动。我上次的方法给我带来了一些麻烦,所以没有代码^^。对servlet的布局有什么建议吗 public class LoaderServlet extends HttpServlet { // The thread to load the needed information private LoaderThread loader; // The last.fm account private Str

嘿,我想实现一个Javaservlet,它只为每个用户启动一次线程。即使在刷新时,也不应再次启动。我上次的方法给我带来了一些麻烦,所以没有代码^^。对servlet的布局有什么建议吗

 public class LoaderServlet extends HttpServlet {
// The thread to load the needed information
private LoaderThread loader;
// The last.fm account
private String lfmaccount;

public LoaderServlet() {
    super();
    lfmaccount = "";
}

@Override
protected void doPost(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    if (loader != null) {
        response.setContentType("text/plain");
        response.setHeader("Cache-Control", "no-cache");
        PrintWriter out = response.getWriter();
        out.write(loader.getStatus());
        out.flush();
        out.close();
    } else {
        loader = new LoaderThread(lfmaccount);
        loader.start();
        request.getRequestDispatcher("WEB-INF/pages/loader.jsp").forward(
                request, response);
    }
}

@Override
protected void doGet(HttpServletRequest request,
        HttpServletResponse response) throws ServletException, IOException {
    if (lfmaccount.isEmpty()) {
        lfmaccount = request.getSession().getAttribute("lfmUser")
                .toString();
    }
    request.getRequestDispatcher("WEB-INF/pages/loader.jsp").forward(
            request, response);
}
}

jsp使用ajax定期发布到servlet并获取状态。该线程只需运行3分钟,就可以抓取一些last.fm数据。

您的第一个任务是找出如何唯一地识别用户,例如,如何识别代理/SOHO网关后面的不同用户

一旦你搞定了,它基本上就是让一个单例对象服务于一个userthread映射到你的servlet

然后我们讨论了@beny23在上面的评论中提到的可伸缩性问题。。。我完全同意你提出的观点——你的方法听起来不明智


干杯,

据我所知,您希望避免并行处理来自同一用户的请求。我建议您使用其他方法:将锁与每个用户关联,并将其存储在会话中。在开始处理用户请求之前,请尝试获取该锁。因此,当前线程将在处理来自该用户的其他请求时等待。(创建会话时,使用会话侦听器存储锁)

这里需要的是。每个浏览器会话只调用一次方法
sessionCreated()
。因此,即使用户刷新页面,也不会出现问题。
然后,您可以继续并为每个
sessionCreated()
方法调用启动线程。

假设可以通过创建
Map
来实现,然后您的servlet被调用,它尝试使用
sessionId
查找映射

只是一个草图:

public class LoaderServlet extends HttpServlet {

  private Map<String,Thread> threadMap = new HashMap<>();

  protected void doPost(..) {
    String sessionId = request.getSesion().getId();
    Thread u = null;
    if(threadMap.containsKey()) {
        u = threadMap.get(sessionId);
    } else {
       u = new Thread(...);
       threadMap.put(sessionId, u);
    }
    // use thread 'u' as you wish
  } 

}
公共类LoaderServlet扩展了HttpServlet{
私有映射threadMap=newhashmap();
受保护的void doPost(…){
字符串sessionId=request.getsession().getId();
线程u=null;
if(threadMap.containsKey()){
u=threadMap.get(sessionId);
}否则{
u=新螺纹(…);
threadMap.put(sessionId,u);
}
//根据需要使用线程“u”
} 
}
注:

  • 这使用会话id,而不是用户来关联线程
  • 看看
    线程池
    ,它们很棒
  • 正如一位评论者所指出的:在这个草图中没有考虑同步问题

实现javax.servlet.SingleThreadModel=>服务方法将不会同时执行。
请参阅servlets规范。

您可以发布您尝试发布的代码吗?您最后的方法是什么?给出一些细节/代码片段。只有这样,我们才能告诉您如何改进它。为什么要为每个用户启动一个线程?我认为这种方法是不可伸缩的,因为这意味着如果你有1000个用户,那么你需要1000个线程(每个都有自己的堆栈,这可能会对你的内存造成严重破坏)。如果你更准确地告诉我们这个目的,也许我们可以提出一个不同的,希望更好的方法来做你想做的事情。在JavaEE世界中,将线程锁定给用户的基本思想对我来说似乎非常不寻常。通常最好让容器管理线程并避免处理线程,因此我的站点上有注册用户。注册后,我必须从他们的帐户中抓取一些最新的FM数据。所以没有什么大任务。我想避免的是他们在浏览器中按refresh键,然后启动新线程^^^^^,当然让多个用户同时抓取他们的内容。这个答案中存在一个并发问题:如果同一会话中同时有两篇帖子,会发生什么?