1. 程式人生 > >記錄ScheduledExecutorService使用中不工作情況

記錄ScheduledExecutorService使用中不工作情況

本文原地址來自於我的個人部落格:www.endless365.com,希望得到各位的關注。

本文詳細地址出自於:http://www.endless365.com/article/get?type=tec&id=154

由於本部落格存在一個自己的IP統計功能,使用了淘寶API查詢IP的歸屬地,由於淘寶API查詢IP歸屬地存在訪問速度限制問題,導致本部落格在插入使用者記錄的時候查詢歸屬地特別的慢,所有考慮使用多執行緒去處理,但是寫了程式碼以後才發現我的阿里雲伺服器是單核的,多執行緒好像沒什麼卵用,好吧,又想了一想,考慮使用一個定時器在晚上某個時候執行。接下來問題就出來了。。。

先上我的程式碼:

ScheduledExecutorService schedule = Executors.newSingleThreadScheduledExecutor();
        schedule.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                try {
                    System.out.println("into updateUserActivityIP=========="+DateTool.getCurrentTimeCN());
                    userActivityService.updateAllUserActivity();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }, 0, 30, TimeUnit.MINUTES);

當啟動tomcat伺服器以後,每隔30分鐘執行一次更新user activity記錄中ip歸屬地的資訊,在測試的過程中發現,into updateUserActivityIP的列印每次都只執行了一次,這個鬱悶啊,查來查去找不到問題的原因。然後就另外寫了一個定時器的demo

/**
 *
 * @author sunny
 */
public class ScheduleTest {
    public static int i=0;
    public static void main(String[] args) {
        ScheduledExecutorService pool = Executors.newSingleThreadScheduledExecutor();
        pool.scheduleAtFixedRate(new Runnable() {

            @Override
            public void run() {
                try {
                    i++;
                    System.out.println("i="+i);
                } catch (Exception ex) {
                    Logger.getLogger(ScheduleTest.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        }, 1, 1, TimeUnit.SECONDS);
    }
}

發現這個Demo沒有任何的問題,好吧,只能去查查JDK的API看在什麼情況下會導致ScheduledExecutorService不工作。發現JDK中有這麼一段話。

QQ截圖20151217092815.jpg

如果任務的任意執行遇到異常,就會取消後續執行。

這句話非常重要,也給了我解決問題的思路。那肯定是我的run方法裡面的程式碼報錯了,但是我又沒有看見後臺有報錯,只要設定一個執行緒預設未捕獲異常的處理handler。

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {

            @Override
            public void uncaughtException(Thread t, Throwable e) {
                e.printStackTrace();
            }
        });

該程式碼放置線上程開啟前面。再次執行以後,果斷髮現了問題。

原來是Hibernate裡面session中事務導致報錯的問題,錯誤如何處理就不詳細講了,解決報錯之後,程式碼就能夠正常執行。

以上文章由於記錄處理這個bug的思路和解決方案。