2011-02-05 174 views
39

任何人都可以在這裏建議?我有一種情況,用戶將通過Java JSP和Servlet交互式地將數據挖掘請求提交給我的應用程序,該應用程序將動態地制定關於數據和更多數據的關聯規則。在Tomcat中運行後臺Java程序

由於這樣的工作可能需要一段時間,我正考慮在服務器上的某種進程在後臺運行這樣的請求,因此它不會鎖定會話,並可能使用大量的服務器記憶不利於系統。

由於該系統由一系列運行在MySQL數據庫的Tomcat容器中的Java JSP和Servlet組成,任何人都可以提出建議嗎?

感謝

摩根先生

+0

你期待給回一個響應?此外,Tomcat使用線程池,可以在必要時擴展以服務多個同時請求。 – 2011-02-05 14:59:37

+0

您是否需要將「數據挖掘請求」的結果顯示回給用戶(或者至少通知他們已完成的作業)?你如何做到這一點? – 2011-02-05 15:02:30

+0

我在想,當一份工作完成後,用戶可以通過電子郵件發送結果。 – 2011-02-05 15:40:28

回答

5

我想Quartz調度應該能夠完成你想要在這裏做什麼。這裏有一些examples from Quartz。使用這個,您可以啓動一個快速輪詢以處理傳入請求的cron。我其實是爲我的一個項目做到了這一點。

48

使用ExecutorService

雖然有幾件事你應該做,將線程標記爲守護程序線程,這樣它至少不會在錯誤場景中綁定tomcat,並且當你的servlet上下文被銷燬時(例如,當你重新部署時或停止您的應用程序要做到這一點,使用的ServletContextListener:

public class ExecutorContextListener implements ServletContextListener { 
    private ExecutorService executor; 

    public void contextInitialized(ServletContextEvent arg0) { 
     ServletContext context = arg0.getServletContext(); 
     int nr_executors = 1; 
     ThreadFactory daemonFactory = new DaemonThreadFactory(); 
     try { 
      nr_executors = Integer.parseInt(context.getInitParameter("nr-executors")); 
     } catch (NumberFormatException ignore) {} 

     if(nr_executors <= 1) { 
     executor = Executors.newSingleThreadExecutor(daemonFactory); 
     } else { 
     executor = Executors.newFixedThreadPool(nr_executors,daemonFactory); 
     } 
      context.setAttribute("MY_EXECUTOR", executor); 
     } 

    public void contextDestroyed(ServletContextEvent arg0) { 
     ServletContext context = arg0.getServletContext(); 
     executor.shutdownNow(); // or process/wait until all pending jobs are done 
    } 

} 
import java.util.concurrent.Executors; 
import java.util.concurrent.ThreadFactory; 

/** 
* Hands out threads from the wrapped threadfactory with setDeamon(true), so the 
* threads won't keep the JVM alive when it should otherwise exit. 
*/ 
public class DaemonThreadFactory implements ThreadFactory { 

    private final ThreadFactory factory; 

    /** 
    * Construct a ThreadFactory with setDeamon(true) using 
    * Executors.defaultThreadFactory() 
    */ 
    public DaemonThreadFactory() { 
     this(Executors.defaultThreadFactory()); 
    } 

    /** 
    * Construct a ThreadFactory with setDeamon(true) wrapping the given factory 
    * 
    * @param thread 
    *   factory to wrap 
    */ 
    public DaemonThreadFactory(ThreadFactory factory) { 
     if (factory == null) 
      throw new NullPointerException("factory cannot be null"); 
     this.factory = factory; 
    } 

    public Thread newThread(Runnable r) { 
     final Thread t = factory.newThread(r); 
     t.setDaemon(true); 
     return t; 
    } 
} 

你必須上下文監聽器添加到你的web.xml,在這裏你還可以指定你想運行的線程數量後臺作業:

<listener> 
    <listener-class>com.example.ExecutorContextListener</listener-class> 
    </listener> 

您可以從你的servlet訪問執行程序和作業提交到它:

ExecutorService executor = (ExecutorService)getServletContext().getAttribute("MY_EXECUTOR"); 
... 
executor.submit(myJob); 

如果你使用Spring,這一切大概可以還送simpler