Many web applications, corporate applications involve long-term operations, such as complex database query or heavy XML processing, etc., although these tasks are mainly completed by database systems or middleware, but the results of the task are still to be sent to users . This article describes a method of improving the user's feeling by improving the front-end performance layer and reducing the server load.
When the 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. Many times, the user will lose patient, then try to click on the browser's refresh button, and finally leave.
The technique described herein is to separate the heavy computing tasks, and operate from a separate thread to solve the above problems. When the user calls the JSP page, the JSP page will return immediately and prompt the user task to be started and executing; the JSP page automatically refreshes yourself, report the current progress of the heavy computing task running in the standalone thread until the task is completed.
First, the simulation task
First we design a Taskbean class, which implements a java.lang.Runnable interface, which runs in a stand-alone thread started by the JSP page (start.jsp). Termination The Run () method is responsible for the STOP.JSP of another JSP page. The TaskBean class also implements the java.io.serializable interface, so the JSP page can be called as a JavaBean:
Package test.barbean;
Import java.io.serializable;
Public Class Taskbean Implements Runnable, SerializAble {
PRIVATE INT Counter;
Private int sum;
Private boolean start;
Private boolean running;
Private int SLEP;
Public taskbean () {
COUNTER = 0;
SUM = 0;
Started = false;
Running = false;
Sleep = 100;
}
}
The "heavy task" containing the taskbean is the value of 1 2 3 ... 100, but it does not calculate the 100 * (100 1) / 2 = 5050 formula, but is called the Work () method by the RUN () method. 100 times completed the calculation. The code for the Work () method is as follows, where Thread.Sleep () is to ensure that the task is always about 10 seconds.
protected void work () {
Try {
Thread.sleep (SLEEP);
Counter ;
SUM = Counter;
} catch (interruptedexception e) {
Strunning (False);
}
}
The Status.jsp page obtains the task's completion status by calling the following getpercent () method:
Public synchronized int getpercent () {
Return Counter;
}
If the task has been started, the isstarted () method will return true:
Public synchronized boolean isstarted () {
Return Started;
}
If the task has been completed, the iScompleted () method will return True:
Public synchronized boolean iscompleted () {
Return counter == 100;
}
If the task is running, the isrunning () method will return 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 wants to mark the task as "already started". Calling setNing (false) means that the RUN () method is required to stop execution.
Public synchronized void setning (Boolean Running) {
THIS.RUNNING = Running;
IF (Running)
Started = true;
}
After the task is executed, call the getResult () method to return to the calculation result; if the task has not been executed, it returns NULL:
Public synchronized Object getResult () {
IF (iScompleted ())
Return New Integer (SUM);
Else
Return NULL;
}
When Running is marked as true, the Completed is marked as false, the run () method calls work (). In practical applications, the Run () method may perform a complex SQL query, parse large XML documents, or call the EJB method that consumes a lot of CPU time. Note that "heavy tasks" may be executed on the remote server. There are two options for the JSP page of the report results: or wait for the task to end, or use a progress bar.
Public void run () {
Try {
Strunning (TRUE);
While (isrunning () &&! iScompleted ())
Work ();
} finally {
Strunning (False);
}
}
Second, start the task
Start.jsp is the welcome page declared in the Web.xml deployment descriptor, the content of web.xml is:
XML Version = "1.0" encoding = "GB2312"?>
Public "- // Sun microsystems, Inc.//dtd Web Application 2.3 // en"
"http://java.sun.com/dtd/web-app_2_3.dtd">
welcome-file-list>
web-app>
Start.jsp starts a dedicated thread to run "heavy tasks" and then pass the HTTP request to status.jsp.
The Start.jsp page creates a TaskBean instance using the
The following is the code list of the Start.jsp page:
<% session.removeattribute ("task");%>
<% task.setrunning (TRUE);%>
<% new thread (task) .Start ();%>
START.JSP creates and sets the TaskBean object, then create a THREAD and incorporate the bean object as a runnable instance. The newly created thread when calling the start () method will perform the Run () method of the taskbean object.
There are now two threads in concurrent execution: the thread of the JSP page (called "JSP thread"), the thread created by the JSP page (called "task thread"). Next, Start.jsp uses the call status.jsp, Status.jsp displays the progress bar and the implementation of the task. Note status.jsp and Start.jsp run in the same JSP thread.
Start.jsp sets the task's Running tag to True before creating a thread so that even when the JSP thread has begun to execute STATUS.JSP, the run () method of the task thread has not started, and it is also possible to ensure that the user will get "the task has Start the status report that starts ".
Set the Running tag to True, starting the task threads These two lines of lines can be moved into the TaskBean to form a new method and then call this new method by the JSP page. In general, the JSP page should try to use Java code as little as possible, ie we should put Java code as much as possible in the Java class. However, in this example we don't follow this rule, put New Thread (task) .Start () directly into Start.jsp Highlight the JSP thread to create and launch the task thread.
Multithreading in the JSP page must be cautious, note that the JSP thread and other thread are actually executed, just in the desktop application, we use a thread to handle the GUI event, and use one or more threads to process Backstage task. However, in the JSP environment, considering the situation of multiple users to request a page, the same JSP page may run simultaneously in multiple threads; in addition, sometimes the same user may send multiple requests to the same page, Although these requests come from the same user, they also cause the server to run multiple threads of a JSP page at the same time.
Third, task progress
The Status.jsp page uses an HTML schedule to display the task's execution. First, status.jsp uses the
Class = "Test.barbean.taskbean" /> In order to reflect the progress of the task in time, Status.jsp automatically refreshes. JavaScript code setTimeout ("Location = 'status.jsp'", 1000) Refresh the page every 1000 milliseconds, reclaiming Status.jsp, does not require user intervention.
<% IF (Task.IsRunning ()) {%>
SetTimeout ("Location = 'status.jsp', 1000); script>
<%}%>
HEAD>
The progress bar is actually an HTML form that contains 10 units - that is, each unit represents 10% of the total task.
Result: <% = task.getResult ()%>
<% int percent = task.getPercent ();%>
<% = percent%>%
H2>
td>
<%}%> <% for (int i = 100; I> percent; i - = 10) {%> | TD>
<%}%> TR> TABLE> The task execution is divided into several states: is executing, completed, has not started, stopped:
|