jojo's blog--快樂憂傷都與你同在
          為夢想而來,為自由而生。 性情若水,風起水興,風息水止,故時而激蕩,時又清平……
          posts - 11,  comments - 30,  trackbacks - 0

               Date,這個大家都認識了,用于保存日期信息,但不推薦進行日期操作及初始化特定日期

               Calendar及其子類GregorianCalendar:日歷類,日期操作,初始化特定日期。

              DateFormat及其子類SimpleDateformat: 日期格式化,日期的默認顯示方式不適合中國人,所以需要格式化為中國人常用的格式來顯示。

              取得當期日期,    Date date=new Date();

              初始化特定日期:假設我們要得到日期為2006-10-27日的對象,需要按如下方式獲得。

                     Calendar cal = new    GregorianCalendar(2006, 9, 27,0,0,0);

                     Date date = cal.getTime();

                 注意:date,getTime()取得的是當期時間的毫秒數,月份比實際的減1

                  GregorianCalendar構造方法參數依次為:年,月-1,日,小時,分,秒      

              格式化為我們熟悉的方式顯示:

                      DateFormat format=new SimpleDateFormat("yyyy-MM-dd HH;mm:ss");

                      String chinesedate = format.format(date);

             日期 年,月,日,分,秒的取得

                      Calendar cal = Calendar.getInstance();

                    int year = cal.get(Calendar.YEAR);

                      int month=cal.get(Calendar.MONTH)+1;

                      int day = cal.get(Calendar.DAY_OF_MONTH);

                       int hour = cal.get(Calendar.HOUR_OF_DAY);

                      int    minute = cal.get(Calendar.MINUTE);

                       int second = cal.get(Calendar.SECOND);

                       注意:月份,實際的月份要比Clendar得到的加1,因為java月份是從0~11

          2.日期基本操作

               得到兩個日期相差的天數

                Date endDate=..

                Date startDate = ...

               相差天數 int days=(int) ((endDate.getTime()-startDate.getTime())/(1000*24*60*60)+0.5);

             得到某個月的天數

                Calendar cal = Calendar.getInstance();

               int month=cal.getActualMaximum(Calendar.DAY_OF_MONTH);

             日期加1天

                cal.add(Calendar.DATE, 1);//日期加1天

                Calendar.YEAR,Calendar.MONTH,Calendar.WEEK_OF_YEAR),分別是年,月,周

          3,java.sql,Date()和java.util.Date();

                前面我們說的都是java.util.Date類,java.sql.Date類是操作數據庫用的日期類型

               java.util.Date date=....

                java.sql.Date sqldate=new java.sql.Date(date.getTime());

               也可以這樣:String date="2005-11-10";

                java.sql.Date sqlDate=java.sql.Date.valueOf(date);

          4,定時器

               a,編寫類,實現TimeTask接口,定時執行的代碼寫入run()方法中

               b.    timer.schedule(TimeTask子類對象, 開始執行的日期, 周期);

               周期為毫秒數

              例子:

              類MyTask:

          import java.util.*;

          public class MyTask extends TimerTask {

                public void run() {

                    System.out.println("MyTask 正在執行...");

                }

          }

              類TimerDemo:

          import java.util.Timer;

          import java.util.Calendar;

          import java.util.GregorianCalendar;

          import java.util.Date;

          public class TimerDemo {

                public static void main(String[] args) {

                    Timer timer = new Timer();

                    MyTask task = new MyTask();

                    Calendar cal = new GregorianCalendar(2006, 9, 28, 12, 49, 0);

                    Date date = cal.getTime();

                    System.out.println("date :" + date.toLocaleString());

                    timer.schedule(task, date, 1000);

                }

          }

          ***********************************************************************************************

          在某些時候, 我們需要實現這樣的功能,某一程序隔一段時間執行一次,而這一事情由系統本身來完成,并不是人為的觸發,我們一般可稱此為定時器任務.

            這類技術主要應用到那些需要進行后臺整理數據的系統中,比如說數據倉儲,數據挖掘等.

            其實到Java中,實現起來是非常簡單的,下面我們以每隔5秒鐘打引一句"Hello world"為例:

          import java.util.TimerTask;

          public class TimeTast extends TimerTask ...{

          // 在這里寫你要定時執行的方法

          public void run() ...

          System.out.println("Hello World!");

          }

          }

          import java.util.Date;

          import java.util.Timer;

          /** *//**

          * 定時器測試

          * @author FeGe

          */

          public class Test ...{

          public void execute() ...{

          Timer timer = new Timer();

          TimeTast myTimeTask = new TimeTast();

          Date date = new Date();

          long timestamp = 5000;

          /** *//**

          * myTimeTask 指定執行的線程 date 指定第一次日期執行的時間 timestamp 指定每格多久再次執行一次

          */

          timer.schedule(myTimeTask, date, timestamp);

          }

          public static void main(String[] args) ...{

          Test t = new Test();

          t.execute();

          }

          }

            一個最簡單的定時器任務就算完成了。是不是太簡單了點呢,其實就這么簡單。

          **************************************************************************************************************

          下面就Servlet偵聽器結合Java定時器來講述整個實現過程。要運用Servlet偵聽器需要實現 javax.servlet.ServletContextListener接口,同時實現它的contextInitialized (ServletContextEvent event)和contextDestroyed(ServletContextEvent event)兩個接口函數。考慮定時器有個建立和銷毀的過程,看了前面兩個接口函數,就不容置疑的把建立的過程置入 contextInitialized,把銷毀的過程置入contextDestroyed了。

          我把ServletContextListener的實現類取名為ContextListener,在其內添加一個定時器,示例代碼如下所示(為考慮篇幅,僅提供部分代碼供讀者參考):

          private java.util.Timer timer = null;

          public void contextInitialized(ServletContextEvent event) {

          timer = new java.util.Timer(true);

          event.getServletContext().log("定時器已啟動");

          timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000);

          event.getServletContext().log("已經添加任務調度表");

          }

          public void contextDestroyed(ServletContextEvent event) {

          timer.cancel();

          event.getServletContext().log("定時器銷毀");

          }

          以 上代碼中, timer.schedule(new MyTask(event.getServletContext()), 0, 60*60*1000)這一行為定時器調度語句,其中MyTask是自定義需要被調度的執行任務(在我的財政數據中心項目中就是報表計算引擎入口),從 java.util.TimerTask繼承,下面會重點講述,第三個參數表示每小時(即60*60*1000毫秒)被觸發一次,中間參數0表示無延遲。 其它代碼相當簡單,不再詳細說明。

          下面介紹MyTask的實現,上面的代碼中看到了在構造MyTask時,傳入了 javax.servlet.ServletContext類型參數,是為記錄Servlet日志方便而傳入,因此需要重載MyTask的構造函數(其父 類java.util.TimerTask原構造函數是沒有參數的)。在timer.schedule()的調度中,設置了每小時調度一次,因此如果想實 現調度任務每24小時被執行一次,還需要判斷一下時鐘點,以常量C_SCHEDULE_HOUR表示(晚上12點,也即0點)。同時為防止24小時執行下 來,任務還未執行完(當然,一般任務是沒有這么長的),避免第二次又被調度以引起執行沖突,設置了當前是否正在執行的狀態標志isRunning。示例代 碼如下所示:

          private static final int C_SCHEDULE_HOUR = 0;

          private static boolean isRunning = false;

          private ServletContext context = null;

          public MyTask(ServletContext context) {

          this.context = context;

          }

          public void run() {

          Calendar cal = Calendar.getInstance();

          if (!isRunning) {

          if (C_SCHEDULE_HOUR == cal.get(Calendar.HOUR_OF_DAY)) {

          isRunning = true;

          context.log("開始執行指定任務");

          //TODO 添加自定義的詳細任務,以下只是示例

          int i = 0;

          while (i++ < 10) {

          context.log("已完成任務的" + i + "/" + 10);

          }

          isRunning = false;

          context.log("指定任務執行結束");

          }

          } else {

          context.log("上一次任務執行還未結束");

          }

          }

          上面代碼中"http://TODO……"之下四行是真正被調度執行的演示代碼(在我的財政數據中心項目中就是報表計算過程),您可以換成自己希望執行的語句。

          到這兒,ServletContextListener和MyTask的代碼都已完整了。最后一步就是把ServletContextListener部署到您的Web工程中去,在您工程的web.xml配置文件中加入如下三行:

          <listener>

          <listener-class>com.test.ContextListener</listener-class>

          </listener>  

          當然,上面的com.test得換成您自己的包名了。保存web.xml文件后,把工程打包部署到Tomcat中即可。任務會在每晚12點至凌晨1點之間被執行,上面的代碼會在Tomcat的日志文件中記錄如下:

          2003-12-05 0:21:39 開始執行指定任務

          2003-12-05 0:21:39 已完成任務的1/10

          ……

          2003-12-05 0:21:39 已完成任務的10/10

          2003-12-05 0:21:39 指定任務執行結束

          posted on 2008-10-26 15:18 Blog of JoJo 閱讀(3428) 評論(7)  編輯  收藏 所屬分類: Java 相關

          FeedBack:
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:25 | Blog of JoJo
          1.開一個定時器1,長度任意。
          2.在定時器1里面判定當前時間。比如距離0:00還有8小時23分12秒,那么關閉定時器1,開定時器2,8小時
          3.在定時器2里判定當前時間。比如距離0:00還有23分12秒,那么關閉定時器2開定時器3,長度23分鐘
          4.在定時器3中開定時器4,時長1秒。當距離0:00為0時,執行操作。然后關閉定時器3開定時器1。
          5.如此往復...

          這樣的話。一天所經歷的判斷的代碼平均也就是100來行。方法簡單,就是定時器,且不會耗什么資源的。
          --------------------------------------------------------------
          思路很好,不過針對系統來說,是否負擔還是一樣.
          系統的ONTIMER,具體怎么實現,我們大家討論一下.-----------------------------------------------------------------------------------------  回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:25 | Blog of JoJo
          計劃任務可以編程實現,比如程序運行一個shell命令 at..../interactive %%%.exe Time....之類的,具體看文檔.但是萬一機器把task服務關閉,就比較麻煩了.

          定時器也可以.

          或者啟動程序的時候記錄一個時間,寫到硬盤上某文件之類的,每隔24小時再執行一下你的那個文件夾操作,還可以當日志用.  回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:26 | Blog of JoJo
          我既然提了這個思路,就說明其可行性。就算你不用ontime,只要主板在加電。時鐘依然跳動,對系統是的負擔,不可說沒有。但是不會影響到正常運行的。就算是計劃任務,原理依然相似。
          ---------------------------------------------------------------------------------
          可行是肯定的,但是否最優就必須討論了.
          我的意思是能否直接調用內核的服務,不要繞彎,這樣能減少消耗.
          當然,最快的方法是硬件中斷,但是這需要做的額外工作很多,不于考慮.

          settimer在user32.dll中實現.這個函數到user32.dll中注冊一個回調函數.
          user32.dll里應該有個循環,到了某個時刻就調用該回調函數.

          madhappy(545454) 的方法基本可行.   回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:37 | Blog of JoJo
          方法是有,程序啟動的時候計算今天(當前日期)的9:30的微秒數,距離現在(當前時間)的微秒數的差,這樣就得到了馬上該運行的是那個時間,下一次運行的間隔的微秒數(一天60×60×24×1000),這樣應該是有辦法做的。   回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:43 | Blog of JoJo
          要在每天9:30和16.30兩個時間定時啟動程序,應該怎么用Timer定時器來實現?
          ===============================================
          方法是有,程序啟動的時候計算今天(當前日期)的9:30的微秒數,距離現在(當前時間)的微秒數的差,這樣就得到了馬上該運行的是那個時間,下一次運行的間隔的微秒數(一天60×60×24×1000),這樣應該是有辦法做的。

          這種情況一般用1個TimerTask控制loading當天的任務.這個TimerTask基本上每天24小時運行一次.只要保證在9點之前運行就可以了
          final Timer timer=new Timer(false);
          timer.schedual(new TimerTask()
          {
          public void run()
          {
          Calendar now=Calendar.getInstance(); //獲得當前時間
          Calendar next1=Calendar.getInstance();
          Calendar next2=Calendar.getInstance();
          next1.set(Calendar.HOUR_OF_DAY,9);//設置鐘頭9點
          next1.set(Calendar.MINUTE,30);//設置分鐘為30
          next2.set(Calendar.HOUR_OF_DAY,16);
          next2.set(Calendar.MINUTE,30);
          timer.schedual(new TimerTask()
          {
          public void run()
          {
          //你9點半要作的事情
          }
          },(next1.getTimeInMillis()-now.getTimeInMillis()));
          //計算現在距離9點半還有多少時間.
          timer.schedual(new TimerTask()
          {
          public void run()
          {//你16點半要作的事情}
          },(next2.getTimeInMillis()-now.getTimeInMillis()));
          }
          },0,24*60*60*1000);24小時運行一次  回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 15:54 | Blog of JoJo
          import java.awt.event.*;
          import java.util.*;

          public class Task implements ActionListener {
          javax.swing.Timer time;
          public Task() {
          //初始化定時器,每分鐘響應一次
          time = new javax.swing.Timer(1000*6, this);
          time.start();
          }

          public void actionPerformed(ActionEvent arg0) {
          Calendar rightNow = Calendar.getInstance();
          if(rightNow.get(Calendar.HOUR_OF_DAY) == 9 ||
          rightNow.get(Calendar.HOUR_OF_DAY) == 16)
          {
          if(Calendar.getInstance().get(Calendar.MINUTE) == 30)
          //9:30或16:30執行任務計劃
          do_task(); }
          return;
          }
          public void do_task() {
          System.out.println("begin ");
          //調用計劃要運行的程序v
          try{
          //Runtime.getRuntime().exec("***.exe");
          }catch(Exception e){}
          }
          public static void main(String[] args) {
          Task a = new Task();
          //死循環讓程序不斷執行
          while(true);
          }
          }  回復  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 16:18 | Blog of JoJo
          ejb3 小結6
          1 ejb的依賴注入
          @Stateless
          @Remote ({Injection.class})
          public class InjectionBean implements Injection {
          @EJB (beanName="HelloWorldBean")
          HelloWorld helloworld;

          public String SayHello() {
          return helloworld.SayHello("注入者");
          }

          這里注入了另一個bean helloworldbean了,還可以用
          mappedName="HellWorldBean/remote
          來指定JNDI


          2 定時服務
          例子:


          import javax.annotation.Resource;
          import javax.ejb.Remote;
          import javax.ejb.SessionContext;
          import javax.ejb.Stateless;
          import javax.ejb.Timeout;
          import javax.ejb.Timer;

          @Stateless
          @Remote ({TimerService.class})
          public class TimerServiceBean implements TimerService {

          private int count = 1;
          private @Resource SessionContext ctx;

          public void scheduleTimer(long milliseconds){
          count = 1;
          ctx.getTimerService().createTimer(new Date(new Date().getTime() + milliseconds),milliseconds, "大家好,這是我的第一個定時器");
          }

          @Timeout
          public void timeoutHandler(Timer timer)
          {
          System.out.println("---------------------");
          System.out.println("定時器事件發生,傳進的參數為: " + timer.getInfo());
          System.out.println("---------------------");

          if (count>=5){
          timer.cancel();//如果定時器觸發5次,便終止定時器
          }
          count++;
          }
          }
          通過依賴注入@Resource SessionContext ctx,我們獲得SessionContext對象,調用ctx.getTimerService().createTimer
          (Date arg0, long arg1, Serializable arg2)方法創建定時器,三個參數的含義如下:
          Date arg0 定時器啟動時間,如果傳入時間小于現在時間,定時器會立刻啟動。
          long arg1 間隔多長時間后再次觸發定時事件。單位:毫秒
          Serializable arg2 你需要傳給定時器的參數,該參數必須實現Serializable接口。
          當定時器創建完成后,我們還需聲明定時器方法。定時器方法的聲明很簡單,只需在方法上面加入@Timeout 注
          釋,另外定時器方法必須遵守如下格式:
          void XXX(Timer timer)
          在定時事件發生時,此方法將被執行。

          在客戶端調用時,可以這樣
          try {
          InitialContext ctx = new InitialContext(props);
          TimerService timer = (TimerService) ctx.lookup("TimerServiceBean/remote");
          timer.scheduleTimer((long)3000);

          }



          3 日期型的注釋

          @Temporal(value=TemporalType.DATE)
          public Date getBirthday() {
          return birthday;
          }

          @Temporal默認為timestamp映射,有三個可以選TemporalType.DATE,TemporalType.time,TemporalType.timestamp



          4 @lob
          如果是大的LOB,最好用延遲加載了
          @Lob
          @Basic(fetch=FetchType.Lazy)
          ......



          5 命名參數查詢
          Query query=em.createQuery("select p from Person P where p.personid=:Id");

          query.setParameter("Id",new Integer(1));



          6 查詢部分屬性
          Query query = em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
          //集合中的元素不再是Person,而是一個Object[]對象數組
          List result = query.getResultList();
          if (result!=null){
          Iterator iterator = result.iterator();
          while( iterator.hasNext() ){
          //取每一行
          Object[] row = ( Object[]) iterator.next();
          //數組中的第一個值是personid
          int personid = Integer.parseInt(row[0].toString());
          String PersonName = row[1].toString();
          out.append("personid="+ personid+ "; Person Name="+PersonName+ "<BR>");
          }
          }


            回復  更多評論
            

          只有注冊用戶登錄后才能發表評論。


          網站導航:
           

          <2008年10月>
          2829301234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章分類

          文章檔案

          新聞分類

          新聞檔案

          相冊

          收藏夾

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 济南市| 肃宁县| 射洪县| 根河市| 乌兰察布市| 汉寿县| 英德市| 读书| 田阳县| 平定县| 泾阳县| 社会| 郑州市| 驻马店市| 赤峰市| 哈尔滨市| 临清市| 乐安县| 德兴市| 浮梁县| 新乡市| 南安市| 临城县| 绥中县| 正定县| 城口县| 通河县| 石景山区| 金平| 云梦县| 灵璧县| 方山县| 绥江县| 彰武县| 明水县| 新化县| 乌鲁木齐县| 博乐市| 永康市| 江北区| 师宗县|