我有一个Web应用程序从数据库中检索(大)结果列表,然后需要通过查看每个结果来减少列表,并丢弃“无效”结果。使结果“无效”的参数是动态的,我们无法将工作传递给数据库。
因此,一个想法是创建一个线程池和ExecutorService并同时检查这些结果。但我一直看到人们说“哦,规范禁止在servlet中产生线程”或“这只是一个坏主意”。
所以,我的问题是:我该怎么办?我在一个servlet 2.5容器中,所以作为3.0规范的一部分的所有异步的好东西都无法使用。编写一个我通过JMS与之通信的单独服务似乎有些过分。
在这里寻找专家意见。
杰森
答案 0 :(得分:5)
无意义。
JEE规范有很多"不应该"并且"你不想"。另一方面,Servlet规范没有。 Servlet规范更加狂野。它实际上并没有深入到JEE规范等实际操作方面。
我还没有看到一个JEE容器(一个纯粹的servlet容器ala Tomcat / Jetty,或者全船ala Glassfish / JBoss)实际上阻止了我自己开出一个线程。 WebSphere可能,它应该是相当臭名昭着的,但我还没有使用过WebSphere。
如果创建不守规矩,自我管理的线程的概念让你发痒,那么完整的JEE容器内部就会有一个正式的#34; WorkManager"可以用来剥离线程。他们只是以不同的方式揭露它们。这本书的内容越多,就越多了#34;获取线程的机制。
但是,坦率地说,我不会打扰。使用标准类库中的Executors可能会取得更大的成功。如果你的系统太多线程使你的系统饱和,一切都失控了,好吧,那就是你。不要这样做(tm)。
至于异步解决方案是否合适,我会对此表示不满。从您的帖子中不清楚它是否是。但你的问题是线程和Servlet。
做到这一点。请注意它可能不是便携式的,并且正确行事(使用执行人员),对此负责,容器不会更明智,也不会小心。
答案 1 :(得分:2)
看起来并发性并不会对你有所帮助。除非检查每个条目非常昂贵,否则同时进行检查不会加快速度。您的瓶颈是通过数据库连接传递结果集,即使您没有在servlet上工作,也无法多线程化。
答案 2 :(得分:2)
没有什么可以阻止你从你的Servlet中找到一些ThreadPool,挑战来自于获得结果。如果Servlet调用期望从您向TreadPool提交任务的结果,您将最终阻止等待TreadPool的内容完成,这样您就可以编写对doGet / doPut调用的响应。
另一方面,如果您设计服务,例如doPut,则将一个任务提交给ThreadPool,但返回一个"句柄"或者任务的一些其他唯一标识符返回给客户端,然后客户端可以"轮询"通过一些doGet API处理句柄以查看任务是否完成。任务完成后,客户端可以获得结果。
答案 3 :(得分:2)
完全正确和合适。我已经对使用不同容器上的线程池的Servlet进行了无数的工作,没有任何问题。
EJB容器(如JBoss)倾向于警告产生线程,但这是因为EJB保证Bean的实例仅由一个线程调用,并且一些设施依赖于此,因此您可能会搞砸了通过使用自己的线程。在Servlet中没有这样的依赖,因此你不能用这种方式搞砸。
即使在EJB容器中,只要您不与自己的线程中的EJB工具进行交互(如调用),就可以使用线程池并保持良好状态。
答案 4 :(得分:1)
使用servlet / threads需要注意的是servlet的成员变量需要是线程安全的。
从技术上讲,没有什么可以阻止你在你的servlet中使用一个线程池进行一些后期处理,但如果你创建一个有20个线程的静态线程池和50个客户端同时访问你的servlet,你可以用脚射击自己,因为30个客户端将等待(取决于你的后期处理需要多长时间)。