13 December 2011

Background Process with Servlet

ที่ใส่ with servlet ไว้ด้วยในหัวเพื่อบอกว่าผมยังจะ extends HttpServlet เหมือนเดิมในคลาสผม แต่ว่าจะทำให้มันทำงานอยู่แม้จะไม่ได้มีรีเควสเข้าไปที่ Servlet ตัวนั้นก็ตาม โดยสิ่งที่ผมจะทำคือการ implement Runnable เข้ามา ตามข้างล่าง
import java.io.IOException;
import java.io.PrintWriter;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@WebServlet(
 name="TestRunnable",
 urlPatterns={"/TestRunnable"},
 loadOnStartup=1
 )
public class TestRunnable extends HttpServlet implements Runnable {

}

ในส่วน annotation Webservlet ผมใส่ loadOnStartup=1 เอาไว้ให้เริ่มทำงานอัตโนมัต เมื่อเรา implement Runnable แล้วเราก็ต้อง override run()
public class TestRunnable extends HttpServlet implements Runnable {
    @Override
    public void run() {
    }

}
method run() ก็คือโค๊ดบล๊อคส่วนที่เราต้องการให้มันทำงานเป็น background process นั้นเองครับ โดยตัวอย่างนี้ผมขอยกตัวอย่างเป็นการนับเลขเพิ่มทีละ 1 ทุกๆ 1 วินาทีแล้วกันครับ
public class TestRunnable extends HttpServlet implements Runnable {
    
    int count = 0;
    Thread thread;

    @Override
    public void init() throws ServletException {
 thread = new Thread(this);
 thread.setPriority(Thread.MIN_PRIORITY);
 thread.start();
    }    

    @Override
    public void run() {
 while(true){
     count++;
     
     try{
  thread.sleep(1000);
     }catch(InterruptedException ignore){}
 }
    }
}
จะเห็นว่ามี method init() เพิ่มเข้ามา method init() เป็น method ที่คอนฟิกค่าเริ่มต้นให้กับอินแสตน เมื่ออินแสตนนี้ถูกสร้าง จะมีการสร้าง thread ของอินแสตนนี้ขึ้นมา
thread = new Thread(this); //เลือกว่าเป็นอินแสตนปัจจุบัน โดยอินแสตนที่เลือกต้อง implement Runnable
โดยจะเซ็ตค่าความสำคัญเป็น MIN เอาไว้แล้วสั่ง start เมื่อทำการ start thread จะเริ่มทำงานตาม method run() ซึ่งก็คื่อเพิ่มค่าให้กับตัวแปร count แล้วทำการหยุด (thread.sleep) 1 วินาที
เมื่อ servlet หยุดทำงานเราต้องทำการหยุด thread ด้วยไม่เช่นนั้นแล้ว thread จะยังคงทำงานต่อไปเรื่อยๆ โดยการ
@Override
    public void destroy() {
 thread.stop();
    }
เพิ่ม method destroy() แล้วสั่ง stop() เท่านี้ก็เป็นอันสิ้นสุดการทำ background process ครับ แต่!!! ถ้าเราเขียนเพียงเท่านี้เราก็จะไม่รู้ว่าโปรแกรมเรานับถึงไหนแล้วเราก็เพิ่มโค๊ดเข้าไปอีกนิดหน่อยแบบนี้ครับ
@WebServlet(
 name="TestRunnable",
 urlPatterns={"/TestRunnable"},
 loadOnStartup=1
 )
public class TestRunnable extends HttpServlet implements Runnable {
    
    int count = 0;
    Thread thread;

    @Override
    public void init() throws ServletException {
 thread = new Thread(this);
 thread.setPriority(Thread.MIN_PRIORITY);
 thread.start();
    }    

    @Override
    public void run() {
 while(true){
     count++;
     
     try{
  thread.sleep(1000);
     }catch(InterruptedException ignore){}
 }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 resp.setContentType("text/plain");
 PrintWriter out = resp.getWriter();
 out.println("Current values : "+count);
    }

    @Override
    public void destroy() {
 thread.stop();
    }
}
โดยส่วนที่เพิ่มก็คือ doGet() นั้นเอง ทีนี้เมื่อเราเปิด servlet หน้านี้เราก็จะเห็นว่า background process นับถึงเท่าไหร่แล้ว

0 comments:

Post a Comment