1. 程式人生 > >Java實現定時排程的三種方法

Java實現定時排程的三種方法

1、Timer

Timer myTimer = new Timer();  

        myTimer.schedule(new Worker(), 1000);//1秒後執行  
//      2012-02-28 09:58:00執行  
        myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"));  
        myTimer.schedule(new Worker(), 5000,1000);//5秒後執行 每一秒執行一次  
//      2012-02-28 09:58:00執行一次 以後每秒執行一次,如果設定的時間點在當前時間之前,任務會被馬上執行,然後開始按照設定的週期定時執行任務  
        myTimer.schedule(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);  
        myTimer.scheduleAtFixedRate(new Worker(), 5000,1000);//5秒後執行 每一秒執行一次 如果該任務因為某些原因(例如垃圾收集)而延遲執行,那麼接下來的任務會盡可能的快速執行,以趕上特定的時間點  
        myTimer.scheduleAtFixedRate(new Worker(), new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2012-02-28 09:58:00"),1000);//和上個類似  

timer的缺點:

(1)Timer對排程的支援是基於絕對時間,而不是相對時間的,由此任務對系統時鐘的改變是敏感的;

(2)所有的TimerTask只有一個執行緒TimerThread來執行,因此同一時刻只有一個TimerTask在執行;

(3)Timer執行緒並不捕獲異常,所以任何一個TimerTask的執行異常都會導致Timer終止所有任務;這種情況下,Timer也不會再重新恢復執行緒的執行了;它錯誤的認為整個Timer都被取消了。此時,已經被安排但尚未執行的TimerTask永遠不會再執行了,新的任務也不能被排程了。


因此你應該考慮使用ScheduledThreadPoolExecutor作為代替品,ScheduledThreadExecutor只支援相對時間。

2、ScheduleExecutorService


ScheduleExecutorService介面中有四個重要的方法,其中scheduleAtFixedRate和scheduleWithFixedDelay在實現定時程式時比較方便。



(1)scheduleAtFixedRate


public ScheduledFuture<?> scheduleAtFixedRate(Runnable command,  
            long initialDelay,  
            long period,  
            TimeUnit unit);  
command:執行執行緒
initialDelay:初始化延時
period:兩次開始執行最小間隔時間

unit:計時單位

(2)scheduleWithFixedDelay

public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,  

                long initialDelay,  
                long delay,  
                TimeUnit unit);  
command:執行執行緒
initialDelay:初始化延時
period:前一次執行結束到下一次執行開始的間隔時間(間隔執行延遲時間)
unit:計時單位

(3)功能示例

1.按指定頻率週期執行某個任務。
初始化延遲0ms開始執行,每隔100ms重新執行一次任務。

/** 
 * 以固定週期頻率執行任務 
 */  
public static void executeFixedRate() {  
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);  
    executor.scheduleAtFixedRate(  
            new EchoServer(),  
            0,  
            100,  
            TimeUnit.MILLISECONDS);  
}  

間隔指的是連續兩次任務開始執行的間隔。

對於scheduleAtFixedRate方法,當執行任務的時間大於我們指定的間隔時間時,它並不會在指定間隔時開闢一個新的執行緒併發執行這個任務。而是等待該執行緒執行完畢。

2.按指定頻率間隔執行某個任務。
初始化時延時0ms開始執行,本次執行結束後延遲100ms開始下次執行。

/** 
 * 以固定延遲時間進行執行 
 * 本次任務執行完成後,需要延遲設定的延遲時間,才會執行新的任務 
 */  
public static void executeFixedDelay() {  
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);  
    executor.scheduleWithFixedDelay(  
            new EchoServer(),  
            0,  
            100,  
            TimeUnit.MILLISECONDS);  

}  

間隔指的是連續上次執行完成和下次開始執行之間的間隔。

3.週期定時執行某個任務。

有時候我們希望一個任務被安排在凌晨3點(訪問較少時)週期性的執行一個比較耗費資源的任務,可以使用下面方法設定每天在固定時間執行一次任務。

/** 
 * 每天晚上8點執行一次 
 * 每天定時安排任務進行執行 
 */  
public static void executeEightAtNightPerDay() {  
    ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);  
    long oneDay = 24 * 60 * 60 * 1000;  
    long initDelay  = getTimeMillis("20:00:00") - System.currentTimeMillis();  
    initDelay = initDelay > 0 ? initDelay : oneDay + initDelay;  
  
    executor.scheduleAtFixedRate(  
            new EchoServer(),  
            initDelay,  
            oneDay,  
            TimeUnit.MILLISECONDS);  
}  

/** 
 * 獲取指定時間對應的毫秒數 
 * @param time "HH:mm:ss" 
 * @return 
 */  
private static long getTimeMillis(String time) {  
    try {  
        DateFormat dateFormat = new SimpleDateFormat("yy-MM-dd HH:mm:ss");  
        DateFormat dayFormat = new SimpleDateFormat("yy-MM-dd");  
        Date curDate = dateFormat.parse(dayFormat.format(new Date()) + " " + time);  
        return curDate.getTime();  
    } catch (ParseException e) {  
        e.printStackTrace();  
    }  
    return 0;  
}  


3、Spring


除了我們自己實現定時任務之外,我們可以使用Spring幫我們完成這樣的事情。
Spring自動定時任務配置方法(我們要執行任務的類名為com.study.MyTimedTask)

<bean id="myTimedTask" class="com.study.MyTimedTask"/>  



<bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
    <property name="targetObject" ref="myTimedTask"/>  
    <property name="targetMethod" value="execute"/>  
    <property name="concurrent" value="false"/>  
</bean>  



<bean id="myTimedTaskTrigger" class="org.springframework.scheduling.quartz.CronTriggerBean">  
    <property name="jobDetail" ref="doMyTimedTask"/>  
    <property name="cronExpression" value="0 0 2 * ?"/>  
</bean>  


<bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    <property name="triggers">  
        <list>  
            <ref local="myTimedTaskTrigger"/>  
        </list>  
    </property>  
</bean>  



<bean id="doScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
    <property name="triggers">  
        <list>  
            <bean class="org.springframework.scheduling.quartz.CronTriggerBean">  
                <property name="jobDetail"/>  
                    <bean id="doMyTimedTask" class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">  
                        <property name="targetObject">  
                            <bean class="com.study.MyTimedTask"/>  
                        </property>  
                        <property name="targetMethod" value="execute"/>  
                        <property name="concurrent" value="false"/>  
                    </bean>  
                </property>  
                <property name="cronExpression" value="0 0 2 * ?"/>  
            </bean>  
        </list>  
    </property>  
</bean>  

相關推薦

Java實現定時排程方法

1、Timer Timer myTimer = new Timer();           myTimer.schedule(new Worker(), 1000);//1秒後執行   //      2012-02-28 09:58:00執行           myT

一、多執行緒基礎概念、實現執行緒方法、中斷執行緒方法,以及執行緒狀態轉化

1、CPU核心數和執行緒數的關係 1:1的關係,引入超執行緒之後,就是1:2 2、cpu時間輪轉機制,即RR排程 3、程序和執行緒 程序:程式執行資源分配最小單位,程序內部有多個執行緒,多個執行緒之間會共享程序資源 執行緒:CPU排程的最小單位 4、並行和併發

前端實現三角形的方法

直接貼程式碼行不行?我是個不善於表達的姑娘QAQ 第一種 HTML+CSS <div class="box"></div> <style> .box{

Java實現克隆的方式

1. 淺克隆      2. 深克隆     3. 利用序列化實現深克隆 1、淺複製(淺克隆)這種淺複製,其實也就是把被複制的這個物件的一些變數值拿過來了。最後生成student2還是一個新的物件。 public class

單鏈表實現反轉的方法

單鏈表的操作是面試中經常會遇到的問題,今天總結一下反轉的幾種方案: 1 ,兩兩對換 2, 放入陣列,倒置陣列 3, 遞迴實現 程式碼如下: #include<stdio.h> #include<malloc.h> typ

JAVA寫JSON的方法java物件轉json資料

今天給大家講一個物件、物件集合轉json資料的三種方法,三種方法最終達到的效果是一樣的。jsonlib:個人感覺最麻煩的一個需要匯入的包也多,程式碼也相對多一些。Gson:google的。FastJson:阿里巴巴的,個人覺得這個比較好,而且據說這個也是效能最好一個。下面就貼

java實現克隆的(很最全面)

1、淺複製(淺克隆)這種淺複製,其實也就是把被複制的這個物件的一些變數值拿過來了。最後生成student2還是一個新的物件。public class CloneTest1 { public static void main(String[] args) throws Exc

Java實現websocket 的兩方法

一.WebSocket簡單介紹  隨著網際網路的發展,傳統的HTTP協議已經很難滿足Web應用日益複雜的需求了。近年來,隨著HTML5的誕生,WebSocket協議被提出,它實現了瀏覽器與伺服器的全雙工通訊,擴充套件了瀏覽器與服務端的通訊功能,使服務端也能主動向客戶端傳送資料。  我們知道,傳統的HTTP協議

java 字串擷取的方法 推薦

                1.split()+正則表示式來進行擷取。 將正則傳入split()。返回的是一個字串陣列型別

Java字串分割的方法

 一、StringTokenizer方法 Java中substring方法可以分解字串,返回的是原字串的一個子字串。如果要講一個字串分解為一個一個的單詞或者標記,StringTokenizer可

java時間格式化的方法

使用fmt函式需在jsp中引入 <%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %><fmt:formatDate value="${item.expDate}" pattern="yyyy-MM-dd"/>

實現servlet介面方法的區別

首先明確,Servlet並不是專門用於處理Http請求的。然後再說三種方式的聯絡和區別。1)原生Servlet介面package javax.servlet; import java.io.IOException; public interface Servlet { public void

RecyclerView實現addHeadView的方法原理說明和利弊分析(footHead同理)

介紹 上一篇部落格我分析了ListView的原始碼看Google是怎麼樣實現addHeadView的,原始碼的思路是對繫結在ListView的Adapter做轉換,在我們呼叫addHeadView的時候把已經寫好的BaseAdapter轉換成HeaderVie

java 載入類的方法

載入類的幾種方法 所有資源都通過ClassLoader載入到JVM裡,那麼在載入資源時當然可以使用ClassLoader,只是對於不同的資源還可以使用一些別的方式載入,例如對於類可以直接new,對於

java 字串擷取的方法(推薦)

1.split()+正則表示式來進行擷取。 將正則傳入split()。返回的是一個字串陣列型別。不過通過這種方式擷取會有很大的效能損耗,因為分析正則非常耗時。 String str = "abc,12,3yy98,0"; String[] strs=str.split(

Java JDBC 連線 Oracle 方法

Java JDBC 連線 Oracle 三種方法 Oracle JDBC 連線ServiceName jdbc:oracle:thin:@//:/ 例:jdbc:oracle:[email protected]//10.1.112.110:1521/H

【c++】模擬實現迴圈佇列 方法(標識、浪費一個空間、計數器)

什麼是迴圈佇列? 為充分利用向量空間,克服”假溢位“現象的方法:將向量空間想象為一個首尾相接的圓環,並稱這種向量為迴圈向量。儲存在其中的佇列稱為迴圈佇列(Circular Queue)。 假象成如圖: 但實際上儲存空間還是一段連續的空間。 空佇列: 當有元素入隊時:

java實現定時任務的方法

/** * 普通thread * 這是最常見的,建立一個thread,然後讓它在while迴圈裡一直執行著, * 通過sleep方法來達到定時任務的效果。這樣可以快速簡單的實現,程式碼如下: * @author GT * */ public class Task

java實現斐波那契數列的方法

Java實現斐波那契數列的三種方法 什麼是斐波那契數列 這裡借用一下度孃的一段話:斐波那契數列(Fibonacci sequence),又稱黃金分割數列、因數學家列昂納多·斐波那契(Leonardoda Fibonacci)以兔子繁殖為例子而引入,故又稱為“兔子數列”,指的是

Java——實現Java多執行緒的方法

Java虛擬機器允許應用程式併發地執行多個執行緒。在Java語言中,多執行緒的實現一般有以下3種方法,其中前兩種是最常用的方法。 1.繼承Thread類,重寫run()方法 Thread本質上也是實現了Runnable介面的一個例項,它代表一個執行緒的例項。並且,啟動執行緒的唯一方法就是通過