我的问题是:
在我的servlet中,我从某个地方获得了大量数据(不相关)。我必须迭代所有这些数据并将其放入一个数组中,将其转换为JSON对象并将其发送到客户端进行查看。如果我在一个响应中执行此操作,则显示结果需要很长时间。因此,我需要做多线程。
创建的线程需要继续向列表添加数据,而主线程每当获得请求时(对数据保持定期请求)都会发送当前可用列表。
例如,在第一次请求时,发送的响应是:1 2 3 第二次请求:4 5 6等等。
现在我遇到了实际问题:我不知道如何在servlet中进行多线程处理。我查看了大量的资源和示例,但它只是让我更加困惑。一些例子在doGet中创建了线程,我认为这是非常错误的,有些已经在init()方法中创建了它们但是我不知道如果在init方法中声明它,我怎么能传递参数并从线程中获取结果(It不能是一个全局变量)。然后是servletContextListener的例子,但我没有发现任何有用或有意义的东西。
任何人都可以向我指导一个可靠的来源,或者只是给我一些伪代码来解决我的问题。如果答案与上述场景相关,那将是非常有帮助的。
由于
答案 0 :(得分:0)
创建的线程需要继续向列表中添加数据 主要线程何时收到请求(数据请求继续 定期发送)发送当前可用列表。
如果我认为你是正确的,你希望得到一些数据作为后台服务,并在他们请求时为客户做好准备(听起来像收获数据)。
好吧,在web-apps中创建线程,或者一般来说托管环境的东西是不同的,隐式创建一个线程会导致内存泄漏。
一个好的解决方案是拥有ThreadPool
(通过容器上下文/ ndi或手动创建)
它必须以可管理的方式创建,您可以通过环境相关事件来控制它。
ContextListener
是你的朋友,有一个上下文监听器类,就像这样。
public class dear_daemon implements ServletContextListener,Runnable{
ExecutorService the_pool;
Thread the_evil;
/*following get invoked once the context is called*/
public void contextInitialized(ServletContextEvent sce){
/*initialize the thread-pool, and run evil thread*/}
/*following get invoked once the context is destroying*/
public void contextDestroyed(ServletContextEvent sce){eviling=false;
/*stop evil(this) thread(first), then destroy thread pool*/
}
volatile boolean eviling=true;
public void run(){
while(eviling){
/*run Runnable instance which do data fetching using thread-pool*/
}
}
}
在web.xml
<listener>
<listener-class>dudes.dear_daemon</listener-class>
</listener>
有一个类(runnable)执行数据获取,并由邪恶的线程调用它,每个实例使用一个线程。
ContextLisstener
可以帮助您正确地关闭和管理容器的init和hult事件,使用与servlet init相同的东西是可能的,但是请确保使用servlet的destroy方法执行相同的操作。
如果你喜欢做关于它的线程事项,请确保你做的是线程安全的事情,因为你有一件事来存储数据(列表)。
如果需要任何同步(例如对所提取的数据进行排序),请确保您正确执行,否则您将面临死锁或低性能代码。
如果需要任何(可能)IO动作来获取数据,请注意java IO是阻塞的,因此设置赞赏读取和连接超时,或者如果您可以处理复杂的NIO内容则切换到NIO。
如果应用这些更改会使环境变得复杂,并且您希望执行其他解决方案,则可以简单地从Web配置文件中提取数据并将其作为外部守护程序 - 服务或应用程序运行,其中applciation将通过提取的内容使用调用CGI / Servlet之一将数据发送到服务器上下文。