Many Web applications, enterprise applications involve long operations, such as complex database queries or heavy XML processing, although these tasks are mainly done by the database system or middleware, but the results of the task execution still need to use JSP to send to the user. This paper introduces a way to improve the user's feeling and reduce the load of the server by improving the front-end performance layer.
When a JSP calls an operation that must run for a long time, and the result of the operation cannot be buffered (on the server side), the user must wait for a long time each time the page is requested. Many times, the user loses patience, then tries to click on the browser's refresh button and finally leaves with disappointment.
The technique described in this article is to isolate the heavy computing task and run it by a separate thread to solve the problem. When a user invokes a JSP page, the JSP page returns immediately, prompting the user that the task is started and executing; the JSP page automatically refreshes itself and reports the current progress of the heavy computing task running on the stand-alone thread until the task is complete.
I. Simulation Tasks
First we design a Taskbean class that implements the Java.lang.Runnable interface, and its run () method runs in a separate thread that is started by the JSP page (start.jsp). Terminating the Run () method is performed by another JSP page stop.jsp. The Taskbean class also implements the Java.io.Serializable interface so that the JSP page can invoke it as a javabean:
package test.barBean;
import java.io.Serializable;
public class TaskBean implements Runnable, Serializable {
private int counter;
private int sum;
private boolean started;
private boolean running;
private int sleep;
public TaskBean() {
counter = 0;
sum = 0;
started = false;
running = false;
sleep = 100;
}
}
Taskbean contains a "heavy task" that calculates the value of 1+2+3...+100, but it does not calculate by 100* (100+1)/2=5050 formula, but by the run () method, which calls the work () method to complete the calculation 100 times. The code for the work () method is as follows, where Thread.Sleep () is invoked to ensure that the task takes about 10 seconds.protected void work() {
try {
Thread.sleep(sleep);
counter++;
sum += counter;
} catch (InterruptedException e) {
setRunning(false);
}
}
The status.jsp page obtains the completion status of a task by calling the following Getpercent () method:public synchronized int getPercent() {
return counter;
}
If the task is already started, the isstarted () method returns true:public synchronized boolean isStarted() {
return started;
}
If the task is completed, the IsCompleted () method returns true:public synchronized boolean isCompleted() {
return counter == 100;
}
If the task is running, the IsRunning () method returns true:public synchronized boolean isRunning() {
return running;
}
The Setrunning () method is called by start.jsp or stop.jsp when the running parameter is true. The Setrunning () method also marks the task as "started." Calling Setrunning (False) indicates that the run () method is required to stop execution.public synchronized void setRunning(boolean running) {
this.running = running;
if (running)
started = true;
}
When the task completes, the call to the GetResult () method returns the result of the calculation, or null if the task has not yet been executed:public synchronized Object getResult() {
if (isCompleted())
return new Integer(sum);
else
return null;
}
When running is marked true and completed is marked false, the run () method calls work (). In practical applications, the run () method may perform complex SQL queries, parse large XML documents, or invoke an EJB method that consumes a lot of CPU time. Note that "heavy tasks" may be performed on a remote server. The JSP page that reports the results has two choices: either wait for the task to end, or use a progress bar.public void run() {
try {
setRunning(true);
while (isRunning() && !isCompleted())
work();
} finally {
setRunning(false);
}
}
Second, start the task
Start.jsp is the Welcome page that is declared in the Web.xml deployment descriptor, and the Web.xml content is:
<?xml version="1.0" encoding="GB2312"?>
<!DOCTYPE web-app
PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
<welcome-file-list>
<welcome-file>start.jsp</welcome-file>
</welcome-file-list>
</web-app>
start.jsp Start > Move a dedicated thread to run a "heavy task" and then pass the HTTP request to status.jsp.
The start.jsp page creates a Taskbean instance with the
Here is the code listing for the start.jsp page:
<% session.removeAttribute("task"); %>
<jsp:useBean id="task" scope="session"
class="test.barBean.TaskBean"/>
<% task.setRunning(true); %>
<% new Thread(task).start(); %>
<jsp:forward page="status.jsp"/>
Start.jsp creates and sets the Taskbean object, it then creates a thread and passes the Bean object as a runnable instance. Calling the start () method the newly created thread executes the Taskbean object's Run () method.
There are now two threads executing concurrently: The thread that executes the JSP page (called the "JSP Thread"), the thread created by the JSP page (called the "Task Thread"). Next, Start.jsp uses the call status.jsp,status.jsp to show the progress bar and the execution of the task. Note that status.jsp and start.jsp are running in the same JSP thread.
start.jsp sets the Taskbean's running tag to true before the thread is created, so that even when the JSP thread has started to perform the status.jsp and the task thread's Run () method has not been started, the user will be assured that the "task started running" 's status report.
Setting the running tag to true, starting the task thread, the two lines of code can move into the Taskbean form a new method, and then the JSP page calls the new method. In general, JSP pages should use less Java code, that is, we should put Java code into Java classes as much as possible. In this case, however, we do not follow this rule, putting the new thread (Task) directly into the start.jsp highlight that the JSP thread created and started the task thread.
Manipulating multithreading in JSP pages must be cautious, noting that JSP threads and other threads actually execute concurrently, as in a desktop application, we use one thread to handle GUI events, and one or more threads to handle background tasks. However, in a JSP environment, the same JSP page may run concurrently in multiple threads, considering that multiple users request a page at the same time, and sometimes the same user may issue multiple requests to the same page, even though the requests are from the same user. They also cause the server to run multiple threads of a JSP page at the same time.