1. 程式人生 > >【SSH網上商城專案實戰15】執行緒、定時器同步首頁資料(類似於部落格定期更新排名)

【SSH網上商城專案實戰15】執行緒、定時器同步首頁資料(類似於部落格定期更新排名)

 

轉自:https://blog.csdn.net/eson_15/article/details/51387378

  上一節我們做完了首頁UI介面,但是有個問題:如果我在後臺添加了一個商品,那麼我必須重啟一下伺服器才能重新同步後臺資料,然後重新整理首頁才能同步資料。這明顯不是我們想要的效果,一般這種網上商城首頁肯定不是人為手動同步資料的,那麼如何解決呢?我們需要用到執行緒和定時器來定時自動同步首頁資料。

1. Timer和TimerTask
        我們需要用到Timer和TimerTask兩個類。先來介紹下這兩個類。

        Timer是一種工具類,在java.util包中,執行緒用其安排以後在後臺執行緒中執行的任務。可安排任務執行一次,或者定期重複執行。它有個建構函式:

Timer(boolean isDaemon)
//建立一個新計時器,可以指定其相關的執行緒作為守護程式執行。
        守護執行緒即主執行緒結束後,該執行緒也結束,非守護執行緒即主執行緒結束後,該執行緒仍然繼續執行。isDaemon為true時為守護執行緒。Timer類有個schedule方法可以建立一個任務,如下:

 

 

void schedule(TimerTask task, Date firstTime, long period) 
//安排指定的任務在指定的時間開始進行重複的固定延遲執行。
//第一個引數是指定任務,即TimerTask物件;第二個引數為第一次開啟任務時間;第三個引數為時間間隔,即每隔多長時間執行一次
        我們再來看看TimerTask,TimerTask是用來建立一個新的執行緒任務的,它實現了Runnable介面,如果我們要建立一個新的執行緒任務,只需要繼承TimerTask,並重寫run方法即可。

 

2. 建立一個新的執行緒任務
        下面我們來建立一個新的執行緒任務,用來更新後臺資料:

複製程式碼
 1 @Component //把該物件交給Spring管理
 2 public class ProductTimerTask extends TimerTask {
 3     
 4     @Resource
 5     private ProductService productService = null; //注入productService
 6     @Resource
 7     private CategoryService categoryService = null; //注入categoryService
 8     
 9     private ServletContext application = null; //定義一個ServletContext物件,因為我們更新了後臺資料後,需要存入application域裡面
10     
11     public void setApplication(ServletContext application) {
12         this.application = application; //通過監聽器將這個application物件set進來,因為這裡是無法拿application物件的
13     }
14     
15     @Override
16      //和監聽器在專案啟動的時候資料初始化的邏輯一樣
17     public void run() {
18         System.out.println("----run----");
19         List<List<Product>> bigList = new ArrayList<List<Product>>(); //bigList中存放一個裝有Category類的list
20          // 1. 查詢出熱點類別
21         for(Category category : categoryService.queryByHot(true)) {
22             //根據熱點類別id獲取推薦商品資訊
23             List<Product> lst = productService.querByCategoryId(category.getId());
24              bigList.add(lst); //將裝有category的list放到bigList中
25         }
26          // 2. 把查詢的bigList交給application內建物件
27          application.setAttribute("bigList", bigList); //假設我們已經拿到了application物件
28     }
29  
30 }
複製程式碼

        接下來,我們修改專案啟動時監聽器裡面的內容,原本上面的這個查詢操作是放在監聽器中,當專案啟動時,監聽器開始執行,獲取後臺資料,存到application域中,然後前臺通過jstl標籤從application域中拿到資料。現在我們把這些事情交給我們定義的ProductTimerTask去做,那麼監聽器中只要設定一下定時器,讓ProductTimerTask定時去更新一下後臺資料即可。看看監聽器中修改後的程式碼:

3. 在監聽器中啟動定時器

 

複製程式碼
 1 //@Component //監聽器是web層的元件,它是tomcat例項化的,不是Spring例項化的。不能放到Spring中
 2 public class InitDataListener implements ServletContextListener {
 3     
 4     private ProductTimerTask productTimerTask = null; //定義一個ProductTimerTask物件
 5     private ApplicationContext context = null;
 6     
 7     @Override
 8     public void contextDestroyed(ServletContextEvent event) {
 9         // TODO Auto-generated method stub
10  
11     }
12  
13     @Override
14     public void contextInitialized(ServletContextEvent event) {
15  
16         context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());                
17         productTimerTask = (ProductTimerTask) context.getBean("productTimerTask");//從配置檔案中獲取ProductTimerTask物件
18  
19         //把內建物件交給productTimerTask,因為productTimerTask裡面是拿不到application的,只能通過監聽器set給它
20         productTimerTask.setApplication(event.getServletContext());
21  
22         //通過設定定時器,讓首頁的資料每個一小時同步一次(配置為守護執行緒)
23         new Timer(true).schedule(productTimerTask, 0, 1000*60*60);//每個一小時執行一次productTimerTask任務,即更新一下後臺資料
24     }
25  
26 }
複製程式碼

 關於InitDataListener監聽器中原來的操作程式碼,可以對比上一節中的內容,其實就是ProductTimerTask中的更新後臺資料,只不過現在放到TimerTask中去做了而已。這樣我們就完成了使用執行緒和定時器定期同步首頁資料,這個時間間隔可以自己設定。

 

        其實CSDN部落格裡的部分首頁資料也不是實時更新的,每天晚上會有個時間更新一次,例如左側欄目中的部落格排名,閱讀排行後的顯示的閱讀量等,這些都是每天晚上更新一次,應該就是在後臺設定了每天更新一次,原理跟這裡應該是一樣的。這樣也減輕了伺服器的壓力。

轉自:https://blog.csdn.net/eson_15/article/details/51387378

  上一節我們做完了首頁UI介面,但是有個問題:如果我在後臺添加了一個商品,那麼我必須重啟一下伺服器才能重新同步後臺資料,然後重新整理首頁才能同步資料。這明顯不是我們想要的效果,一般這種網上商城首頁肯定不是人為手動同步資料的,那麼如何解決呢?我們需要用到執行緒和定時器來定時自動同步首頁資料。

1. Timer和TimerTask
        我們需要用到Timer和TimerTask兩個類。先來介紹下這兩個類。

        Timer是一種工具類,在java.util包中,執行緒用其安排以後在後臺執行緒中執行的任務。可安排任務執行一次,或者定期重複執行。它有個建構函式:

Timer(boolean isDaemon)
//建立一個新計時器,可以指定其相關的執行緒作為守護程式執行。
        守護執行緒即主執行緒結束後,該執行緒也結束,非守護執行緒即主執行緒結束後,該執行緒仍然繼續執行。isDaemon為true時為守護執行緒。Timer類有個schedule方法可以建立一個任務,如下:

 

 

void schedule(TimerTask task, Date firstTime, long period) 
//安排指定的任務在指定的時間開始進行重複的固定延遲執行。
//第一個引數是指定任務,即TimerTask物件;第二個引數為第一次開啟任務時間;第三個引數為時間間隔,即每隔多長時間執行一次
        我們再來看看TimerTask,TimerTask是用來建立一個新的執行緒任務的,它實現了Runnable介面,如果我們要建立一個新的執行緒任務,只需要繼承TimerTask,並重寫run方法即可。

 

2. 建立一個新的執行緒任務
        下面我們來建立一個新的執行緒任務,用來更新後臺資料:

複製程式碼
 1 @Component //把該物件交給Spring管理
 2 public class ProductTimerTask extends TimerTask {
 3     
 4     @Resource
 5     private ProductService productService = null; //注入productService
 6     @Resource
 7     private CategoryService categoryService = null; //注入categoryService
 8     
 9     private ServletContext application = null; //定義一個ServletContext物件,因為我們更新了後臺資料後,需要存入application域裡面
10     
11     public void setApplication(ServletContext application) {
12         this.application = application; //通過監聽器將這個application物件set進來,因為這裡是無法拿application物件的
13     }
14     
15     @Override
16      //和監聽器在專案啟動的時候資料初始化的邏輯一樣
17     public void run() {
18         System.out.println("----run----");
19         List<List<Product>> bigList = new ArrayList<List<Product>>(); //bigList中存放一個裝有Category類的list
20          // 1. 查詢出熱點類別
21         for(Category category : categoryService.queryByHot(true)) {
22             //根據熱點類別id獲取推薦商品資訊
23             List<Product> lst = productService.querByCategoryId(category.getId());
24              bigList.add(lst); //將裝有category的list放到bigList中
25         }
26          // 2. 把查詢的bigList交給application內建物件
27          application.setAttribute("bigList", bigList); //假設我們已經拿到了application物件
28     }
29  
30 }
複製程式碼

        接下來,我們修改專案啟動時監聽器裡面的內容,原本上面的這個查詢操作是放在監聽器中,當專案啟動時,監聽器開始執行,獲取後臺資料,存到application域中,然後前臺通過jstl標籤從application域中拿到資料。現在我們把這些事情交給我們定義的ProductTimerTask去做,那麼監聽器中只要設定一下定時器,讓ProductTimerTask定時去更新一下後臺資料即可。看看監聽器中修改後的程式碼:

3. 在監聽器中啟動定時器

 

複製程式碼
 1 //@Component //監聽器是web層的元件,它是tomcat例項化的,不是Spring例項化的。不能放到Spring中
 2 public class InitDataListener implements ServletContextListener {
 3     
 4     private ProductTimerTask productTimerTask = null; //定義一個ProductTimerTask物件
 5     private ApplicationContext context = null;
 6     
 7     @Override
 8     public void contextDestroyed(ServletContextEvent event) {
 9         // TODO Auto-generated method stub
10  
11     }
12  
13     @Override
14     public void contextInitialized(ServletContextEvent event) {
15  
16         context = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());                
17         productTimerTask = (ProductTimerTask) context.getBean("productTimerTask");//從配置檔案中獲取ProductTimerTask物件
18  
19         //把內建物件交給productTimerTask,因為productTimerTask裡面是拿不到application的,只能通過監聽器set給它
20         productTimerTask.setApplication(event.getServletContext());
21  
22         //通過設定定時器,讓首頁的資料每個一小時同步一次(配置為守護執行緒)
23         new Timer(true).schedule(productTimerTask, 0, 1000*60*60);//每個一小時執行一次productTimerTask任務,即更新一下後臺資料
24     }
25  
26 }
複製程式碼

 關於InitDataListener監聽器中原來的操作程式碼,可以對比上一節中的內容,其實就是ProductTimerTask中的更新後臺資料,只不過現在放到TimerTask中去做了而已。這樣我們就完成了使用執行緒和定時器定期同步首頁資料,這個時間間隔可以自己設定。

 

        其實CSDN部落格裡的部分首頁資料也不是實時更新的,每天晚上會有個時間更新一次,例如左側欄目中的部落格排名,閱讀排行後的顯示的閱讀量等,這些都是每天晚上更新一次,應該就是在後臺設定了每天更新一次,原理跟這裡應該是一樣的。這樣也減輕了伺服器的壓力。