【发布时间】:2014-07-30 07:55:51
【问题描述】:
我有一个带有 3 个输入字段的 HTML 页面,当用户单击提交按钮时,使用 jQuery 向具有 3 个字段的内容的 servlet 发出 AJAX 请求。
当请求到达服务器(我的servlet)时,我需要为每个输入字段创建一个线程,并管理这个线程池,将它们按顺序排列。
例如;如果线程 1 较早完成,则线程 2 应在下一个线程之前将响应打印给客户端。我目前在每个线程中使用随机睡眠时间的睡眠方法,以确定每个线程应该花费的时间。
在客户端,在 HTML 中,我有一个元素来显示响应。
要将信息发送给客户端,我只需要在 servlet 端调用PrintWriter.write。
我遇到的问题是每个线程的信息同时出现在客户端。
只有在所有线程都完成后,输出才会出现在客户端。
例如;我有线程 a 需要 200 毫秒,线程 b 需要 300 毫秒,线程 c 需要 100 毫秒。
客户端的结果只会在 300 毫秒后出现,例如结果是字符串“cab”。
所以我的 HTML 页面上有以下 JavaScript 函数:
$.ajax({
type : 'get',
url : 'ServletResponse2',
data : {
"name1" : name1,"name2" : name2, "name3" : name3
},
success : function(xhr,data) {
console.log("xhr:"+xhr);
console.log("xhr text:"+xhr.responseText);
console.log("data:"+data);
console.log("data2:"+data.data);
$("#listResponse2").append("<li>" + xhr);
$("#listResponse2").append("</li>");
},
complete : function(xhr,data) {
response = xhr.responseText;
console.log("exception:"+response);
$("#listResponse").append("<li>" + response);
$("#listResponse").append("</li>");
},
error : function(e) {
console.log("exception:"+e);
}
});
然后,在 servlet 中,我有这个 get 方法调用一个执行器服务,它调用一个实现 Runnable 的类工作线程:
protected void doGet(HttpServletRequest request,HttpServletResponse response)
{
ExecutorService executor= Executors.newFixedThreadPool(3);
PrintWriter out=null;
response.setCharacterEncoding("UTF-8");
String name1 = request.getParameter("name1");
String name2 = request.getParameter("name2");
String name3 = request.getParameter("name3");
String name="";
for (int i = 1; i < 4; i++) {
name=request.getParameter("name"+i);
try {
out = response.getWriter();
Runnable worker = new WorkerThread("" + name,response);
executor.execute(worker);
} catch (IOException e) {
e.printStackTrace();
}
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
out.print(name);
}
在WorkerThread.java 中,我创建了一个run() 方法,它为每个servlet 编写响应,我什至使用了out.flush() 和response.flushbuffer() 方法。
public class WorkerThread implements Runnable {
private String command;
PrintWriter out;
HttpServletResponse response;
public WorkerThread(String s,HttpServletResponse sresponse){
this.command=s;
this.response=sresponse;
}
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
try {
out = response.getWriter();
out.write(command);
out.flush();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
processCommand();
System.out.println(Thread.currentThread().getName()+" End.");
}
private void processCommand() {
try {
Long time=(long)(Math.random() * 5000);
Thread.sleep(time);
System.out.println("Thread.getName():"+Thread.currentThread().getName()+"|comand:"+command+"|time:"+ time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public String toString(){
return this.command;
}
}
我也尝试在执行器服务中使用Callabe,而不是Runnable,但结果是一样的。谁能告诉我我做错了什么,为什么线程的结果同时到达客户端?
【问题讨论】:
-
为什么?您要解决的真正问题是什么?