Multithreading JavaEE:线程中的构建和刷新响应
我正在尝试编写一个线程化的JavaEEservlet。 每个线程将使用HTTP传输编码:chunked在单个HTTP块中执行一些处理并写入其结果。 每个数据块一可用就会被发送到客户端。 我在每个线程中写入和刷新输出时遇到问题。 例如,下面的代码生成5个线程,这些线程生成一个随机字符串,将其写入输出缓冲区,并通过同步函数调用刷新该缓冲区Multithreading JavaEE:线程中的构建和刷新响应,multithreading,jakarta-ee,thread-safety,Multithreading,Jakarta Ee,Thread Safety,我正在尝试编写一个线程化的JavaEEservlet。 每个线程将使用HTTP传输编码:chunked在单个HTTP块中执行一些处理并写入其结果。 每个数据块一可用就会被发送到客户端。 我在每个线程中写入和刷新输出时遇到问题。 例如,下面的代码生成5个线程,这些线程生成一个随机字符串,将其写入输出缓冲区,并通过同步函数调用刷新该缓冲区 public class TestServer extends HttpServlet { private PrintWriter m_out; p
public class TestServer extends HttpServlet {
private PrintWriter m_out;
public TestServer() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
m_out = response.getWriter();
m_out.print("gonna start\n");
m_out.flush();
ThreadPoolExecutor thread_pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
for(int i = 0; i < 5; i++ ) {
thread_pool.execute(new Runnable() {
private ReentrantLock m_lock = new ReentrantLock();
@Override
public void run() {
SecureRandom random = new SecureRandom();
m_lock.lock();
try {
display(new BigInteger(1300, random).toString(32)+"\n");
}
finally {
m_lock.unlock();
}
}
});
}
thread_pool.shutdown();
try {
thread_pool.awaitTermination(120, TimeUnit.SECONDS);
}
catch (InterruptedException e1) {
log("thread interrupted");
e1.printStackTrace();
}
m_out.print("ok we done\n");
m_out.close();
}
void display(String content) {
m_out.print(content);
m_out.flush();
}
}
您可以看到,第一个动态生成的行是重复的。
这似乎表明PrintWriter.flush方法无法同步
为什么这不起作用,我能做些什么来实现我的目标
谢谢。为了将来的参考,我想我用以下代码实现了它:
@SuppressWarnings("serial")
public class TestServer extends HttpServlet {
private final int THREADPOOL_SIZE = 10;
private ThreadPoolExecutor thread_pool;
public void init(ServletConfig config) throws ServletException {
super.init(config);
thread_pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(THREADPOOL_SIZE);
}
public void destroy() {
thread_pool.shutdownNow();
}
public TestServer() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
CompletionService<String> completion_service_pool = new ExecutorCompletionService<String>(thread_pool);
int task_num = 10;
final int line_length = 13000;
for(int i = 0; i < task_num; i++) {
completion_service_pool.submit(new Callable<String>(){
@Override
public String call() {
Random rn = new Random();
int sleep_seconds = Math.abs(rn.nextInt() % 10);
try {
Thread.sleep(sleep_seconds * 1000);
}
catch (Exception e) {
}
return String.format("Slept for %d seconds. %s<br>\n", sleep_seconds, new BigInteger(line_length, rn).toString(32));
}
});
}
PrintWriter out = response.getWriter();
response.setContentType("text/html");
out.print("gonna start<br>\n");
out.flush();
for(int i = 0; i < task_num; ) {
try {
Future<String> result_task = completion_service_pool.poll();
if(result_task != null) {
String result_string = result_task.get();
out.print(result_string);
out.flush();
i++;
}
}
catch (Exception e) {
}
}
out.print("ok we done<br>\n");
out.close();
}
}
@SuppressWarnings("serial")
public class TestServer extends HttpServlet {
private final int THREADPOOL_SIZE = 10;
private ThreadPoolExecutor thread_pool;
public void init(ServletConfig config) throws ServletException {
super.init(config);
thread_pool = (ThreadPoolExecutor) Executors.newFixedThreadPool(THREADPOOL_SIZE);
}
public void destroy() {
thread_pool.shutdownNow();
}
public TestServer() {
super();
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
CompletionService<String> completion_service_pool = new ExecutorCompletionService<String>(thread_pool);
int task_num = 10;
final int line_length = 13000;
for(int i = 0; i < task_num; i++) {
completion_service_pool.submit(new Callable<String>(){
@Override
public String call() {
Random rn = new Random();
int sleep_seconds = Math.abs(rn.nextInt() % 10);
try {
Thread.sleep(sleep_seconds * 1000);
}
catch (Exception e) {
}
return String.format("Slept for %d seconds. %s<br>\n", sleep_seconds, new BigInteger(line_length, rn).toString(32));
}
});
}
PrintWriter out = response.getWriter();
response.setContentType("text/html");
out.print("gonna start<br>\n");
out.flush();
for(int i = 0; i < task_num; ) {
try {
Future<String> result_task = completion_service_pool.poll();
if(result_task != null) {
String result_string = result_task.get();
out.print(result_string);
out.flush();
i++;
}
}
catch (Exception e) {
}
}
out.print("ok we done<br>\n");
out.close();
}
}