我使用运行servlet的Tomcat开发了一个简单的服务器。
servlet调用命令行程序 - 执行大约需要20秒,然后通过JSON将结果返回给用户。问题是 - 如果我同时发出2个以上的请求,则servlet会阻塞,直到完成之前的一个请求。
下面可以看到一个例子 - “Im in”是servlet的顶部,结果列表是在servlet执行之后。所有请求都是在同一时间提出的 - 但您可以清楚地看到它们不会同时处理。我需要在tomcat中更改哪些设置才能同时处理所有请求?
Im in Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE Im in FVFNT01 STOP_IDLE FVFNT03 STOP_IDLE FVFNT16 STOP_IDLE FVFNT17 STOP_IDLE
答案 0 :(得分:1)
默认情况下,对servlet的请求是并发处理的。没有启用/禁用此行为的设置。这由JavaDoc for HttpServlet确认:
通常运行Servlet 多线程服务器,所以要注意 servlet必须处理并发 请求并小心同步 访问共享资源。
但是,如果您的servlet实现了标记接口SingleThreadModel,则servlet将一次只处理一个请求。但是,使用这个界面通常被认为是一种不好的做法,因为你没有提到它,我认为你没有使用它。
当然,即使您没有实现SingleThreadModel
,也可以使用(可能不适当的)同步来进行任何servlet单线程,例如。
class MyServlet extends HttpServlet {
private void Object sharedObject = new Object()
protected synchronized void doGet(HttpServletRequest req, HttpServletResponse resp) {
// method logic goes here
}
protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
synchronized(sharedObject) {
// method logic goes here
}
}
protected void doPut(HttpServletRequest req, HttpServletResponse resp) {
synchronized(this) {
// method logic goes here
}
}
}
在上面的示例中,一次只有一个线程可以执行相同的请求方法,尽管可以(例如)一个线程执行doPost()
而另一个线程执行doGet()
如果您不明白为什么会这样,那么我建议您在进一步研究问题之前先阅读Java中的并发编程。
答案 1 :(得分:1)
问题在于您的测试客户端。它同步触发请求。它应该异步触发请求,然后servlet将能够执行相同的操作:)
大致相同的问题在4天前被问到,我已经发布了一个代码示例的答案,测试客户端应该如何:Servlet requests are executed sequentially for no apparent reason in Glassfish v3。您可能会发现它也很有用。
答案 2 :(得分:0)
确保您的请求使用不同的HTTP连接并检查您的tomcat配置是否允许超过1个线程(默认情况下确实如此,所以除非您更改它,否则应该没问题。)
答案 3 :(得分:0)
一旦你在Tomcat上运行app(而不是在调试模式下通过eclipse),对同一服务器的相同请求将被线程化。
可以完成一个简单的测试用例: 制作一些简单的doGet,它将做下一件事:
PrintWriter printWriter = response.getWriter();
printWriter.append("doGet: Hello from testServlet! doing some thread check :)");
try{Thread.sleep(15*1000);}catch(Exception e){}
printWriter.close();
现在运行Web浏览器并多次运行此servlet,您将看到所有这些都同时返回(+ - )。 如果servlet没有线程,你会期望第一个将在15秒后返回,第二个在30秒后返回等等......