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

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

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

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

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

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

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

                     Date date = cal.getTime();

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

                  GregorianCalendar構(gòu)造方法參數(shù)依次為:年,月-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);

                       注意:月份,實(shí)際的月份要比Clendar得到的加1,因?yàn)閖ava月份是從0~11

          2.日期基本操作

               得到兩個日期相差的天數(shù)

                Date endDate=..

                Date startDate = ...

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

             得到某個月的天數(shù)

                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類是操作數(shù)據(jù)庫用的日期類型

               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,編寫類,實(shí)現(xiàn)TimeTask接口,定時執(zhí)行的代碼寫入run()方法中

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

               周期為毫秒數(shù)

              例子:

              類MyTask:

          import java.util.*;

          public class MyTask extends TimerTask {

                public void run() {

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

                }

          }

              類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);

                }

          }

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

          在某些時候, 我們需要實(shí)現(xiàn)這樣的功能,某一程序隔一段時間執(zhí)行一次,而這一事情由系統(tǒng)本身來完成,并不是人為的觸發(fā),我們一般可稱此為定時器任務(wù).

            這類技術(shù)主要應(yīng)用到那些需要進(jìn)行后臺整理數(shù)據(jù)的系統(tǒng)中,比如說數(shù)據(jù)倉儲,數(shù)據(jù)挖掘等.

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

          import java.util.TimerTask;

          public class TimeTast extends TimerTask ...{

          // 在這里寫你要定時執(zhí)行的方法

          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 指定執(zhí)行的線程 date 指定第一次日期執(zhí)行的時間 timestamp 指定每格多久再次執(zhí)行一次

          */

          timer.schedule(myTimeTask, date, timestamp);

          }

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

          Test t = new Test();

          t.execute();

          }

          }

            一個最簡單的定時器任務(wù)就算完成了。是不是太簡單了點(diǎn)呢,其實(shí)就這么簡單。

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

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

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

          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("已經(jīng)添加任務(wù)調(diào)度表");

          }

          public void contextDestroyed(ServletContextEvent event) {

          timer.cancel();

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

          }

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

          下面介紹MyTask的實(shí)現(xiàn),上面的代碼中看到了在構(gòu)造MyTask時,傳入了 javax.servlet.ServletContext類型參數(shù),是為記錄Servlet日志方便而傳入,因此需要重載MyTask的構(gòu)造函數(shù)(其父 類java.util.TimerTask原構(gòu)造函數(shù)是沒有參數(shù)的)。在timer.schedule()的調(diào)度中,設(shè)置了每小時調(diào)度一次,因此如果想實(shí) 現(xiàn)調(diào)度任務(wù)每24小時被執(zhí)行一次,還需要判斷一下時鐘點(diǎn),以常量C_SCHEDULE_HOUR表示(晚上12點(diǎn),也即0點(diǎn))。同時為防止24小時執(zhí)行下 來,任務(wù)還未執(zhí)行完(當(dāng)然,一般任務(wù)是沒有這么長的),避免第二次又被調(diào)度以引起執(zhí)行沖突,設(shè)置了當(dāng)前是否正在執(zhí)行的狀態(tài)標(biāo)志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("開始執(zhí)行指定任務(wù)");

          //TODO 添加自定義的詳細(xì)任務(wù),以下只是示例

          int i = 0;

          while (i++ < 10) {

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

          }

          isRunning = false;

          context.log("指定任務(wù)執(zhí)行結(jié)束");

          }

          } else {

          context.log("上一次任務(wù)執(zhí)行還未結(jié)束");

          }

          }

          上面代碼中"http://TODO……"之下四行是真正被調(diào)度執(zhí)行的演示代碼(在我的財(cái)政數(shù)據(jù)中心項(xiàng)目中就是報(bào)表計(jì)算過程),您可以換成自己希望執(zhí)行的語句。

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

          <listener>

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

          </listener>  

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

          2003-12-05 0:21:39 開始執(zhí)行指定任務(wù)

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

          ……

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

          2003-12-05 0:21:39 指定任務(wù)執(zhí)行結(jié)束

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

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

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

          定時器也可以.

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

          settimer在user32.dll中實(shí)現(xiàn).這個函數(shù)到user32.dll中注冊一個回調(diào)函數(shù).
          user32.dll里應(yīng)該有個循環(huán),到了某個時刻就調(diào)用該回調(diào)函數(shù).

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

          這種情況一般用1個TimerTask控制loading當(dāng)天的任務(wù).這個TimerTask基本上每天24小時運(yùn)行一次.只要保證在9點(diǎn)之前運(yùn)行就可以了
          final Timer timer=new Timer(false);
          timer.schedual(new TimerTask()
          {
          public void run()
          {
          Calendar now=Calendar.getInstance(); //獲得當(dāng)前時間
          Calendar next1=Calendar.getInstance();
          Calendar next2=Calendar.getInstance();
          next1.set(Calendar.HOUR_OF_DAY,9);//設(shè)置鐘頭9點(diǎn)
          next1.set(Calendar.MINUTE,30);//設(shè)置分鐘為30
          next2.set(Calendar.HOUR_OF_DAY,16);
          next2.set(Calendar.MINUTE,30);
          timer.schedual(new TimerTask()
          {
          public void run()
          {
          //你9點(diǎn)半要作的事情
          }
          },(next1.getTimeInMillis()-now.getTimeInMillis()));
          //計(jì)算現(xiàn)在距離9點(diǎn)半還有多少時間.
          timer.schedual(new TimerTask()
          {
          public void run()
          {//你16點(diǎn)半要作的事情}
          },(next2.getTimeInMillis()-now.getTimeInMillis()));
          }
          },0,24*60*60*1000);24小時運(yùn)行一次  回復(fù)  更多評論
            
          # 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() {
          //初始化定時器,每分鐘響應(yīng)一次
          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執(zhí)行任務(wù)計(jì)劃
          do_task(); }
          return;
          }
          public void do_task() {
          System.out.println("begin ");
          //調(diào)用計(jì)劃要運(yùn)行的程序v
          try{
          //Runtime.getRuntime().exec("***.exe");
          }catch(Exception e){}
          }
          public static void main(String[] args) {
          Task a = new Task();
          //死循環(huán)讓程序不斷執(zhí)行
          while(true);
          }
          }  回復(fù)  更多評論
            
          # re: java日期操作 及 Timer定時器
          2008-10-26 16:18 | Blog of JoJo
          ejb3 小結(jié)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 定時服務(wù)
          例子:


          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("定時器事件發(fā)生,傳進(jìn)的參數(shù)為: " + timer.getInfo());
          System.out.println("---------------------");

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

          在客戶端調(diào)用時,可以這樣
          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默認(rèn)為timestamp映射,有三個可以選TemporalType.DATE,TemporalType.time,TemporalType.timestamp



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



          5 命名參數(shù)查詢
          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[]對象數(shù)組
          List result = query.getResultList();
          if (result!=null){
          Iterator iterator = result.iterator();
          while( iterator.hasNext() ){
          //取每一行
          Object[] row = ( Object[]) iterator.next();
          //數(shù)組中的第一個值是personid
          int personid = Integer.parseInt(row[0].toString());
          String PersonName = row[1].toString();
          out.append("personid="+ personid+ "; Person Name="+PersonName+ "<BR>");
          }
          }


            回復(fù)  更多評論
            

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


          網(wǎng)站導(dǎo)航:
           

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

          常用鏈接

          留言簿(6)

          隨筆檔案

          文章分類

          文章檔案

          新聞分類

          新聞檔案

          相冊

          收藏夾

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 宽甸| 乐昌市| 金堂县| 林甸县| 夏河县| 仲巴县| 台前县| 咸阳市| 隆化县| 修武县| 定结县| 永济市| 密云县| 乌拉特前旗| 咸丰县| 凤山市| 永仁县| 昌图县| 凤阳县| 邵武市| 河南省| 驻马店市| 铜陵市| 富阳市| 怀来县| 和硕县| 六枝特区| 罗田县| 准格尔旗| 天峻县| 开阳县| 海伦市| 镇康县| 长子县| 新安县| 施秉县| 林芝县| 唐海县| 绩溪县| 文成县| 舒城县|