java實現定時任務


普通thread--

 這是最常見的, 創建一個thread,然后讓它在while循環里一直運行着,
 通過sleep方法來達到定時任務的效果。這樣可以快速簡單的實現,
package com.iotek.classtype;

public class Task1 {
   public static void main(String[] args) {
    final long timeInterval=1000;
    Runnable runnable =new Runnable() {
        
        @Override
        public void run() {
            while(true) {
                 System.out.println("hello !!!");
                 
                 try {
                    Thread.sleep(timeInterval);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
    };
    Thread thread=new Thread(runnable);
    thread.start();
}
}

 

Timer類

Timer類可以調度任務,TimerTask則是通過在run()方法里實現具體任務。 Timer實例可以調度多任務,它是線程安全的。

 

 當Timer的構造器被調用時,它創建了一個線程,這個線程可以用來調度任務。 下面是代碼:
通過
timer.schedule()方法
package com.iotek.classtype;

import java.util.Timer;
import java.util.TimerTask;

public class Task2 {
  public static void main(String[] args) {
    
      TimerTask  timerTask=new TimerTask() {
        
        @Override
        public void run() {
            System.out.println("HELLO");
            
        }
    };
    
    Timer timer=new Timer();
    long delay=0;
    long intevalPeriod=1*1000;
    timer.schedule(timerTask, delay, intevalPeriod);
}
}

ScheduledExecutorService

ScheduledExecutorService是從Java SE5的java.util.concurrent里,做為並發工具類被引進的,這是最理想的定時任務實現方式。

相比於上兩個方法,它有以下好處:

  相比於Timer的單線程,它是通過線程池的方式來執行任務的

  可以很靈活的去設定第一次執行任務delay時間

  提供了良好的約定,以便設定執行的時間間隔

package com.iotek.classtype;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class Task3 {
 public static void main(String[] args) {
    
     Runnable runnable=new Runnable() {
        
        @Override
        public void run() {
        System.out.println("hello");
        }
    };
    ScheduledExecutorService service=Executors.newSingleThreadScheduledExecutor();
    service.scheduleAtFixedRate(runnable, 10,1,TimeUnit.SECONDS);
}
}

JAVA實現定時任務的幾種方式

  • JDK 自帶的定時器實現

Timer類 
這個類允許你調度一個java.util.TimerTask任務。主要有以下幾個方法:

 //schedule(TimerTask task, long delay) 延遲 delay 毫秒 執行
   public static void main(String[] args) {
    for(int i=0;i<10;i++) {
        new Timer().schedule(new TimerTask() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+" run");
                
            }
        }, 1000);
    }
View Code
//schedule(TimerTask task, Date time) 特定時間執行
    public static void main(String[] args) {
        for (int i = 0; i <20; i++) {
            new Timer("TIMER"+i).schedule(new TimerTask() {
                
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+" RUN");
                    
                }
            }, new Date(System.currentTimeMillis()+2000));
        }
    }
View Code
//schedule(TimerTask task, long delay, long period) 延遲 delay 執行並每隔period 執行一次
    public static void main(String[] args) {
        for (int i = 0; i < 10; i++) {
           new Timer(" timer"+i).scheduleAtFixedRate(new TimerTask() {
            
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName()+"run");
                
            }
        }, 1000, 2000);    
        }
    }
View Code

ScheduledExecutorService 接口實現類 
ScheduledExecutorService 是JAVA 1.5 后新增的定時任務接口,主要有以下幾個方法。

ScheduledFuture<?> schedule(Runnable command,long delay, TimeUnit unit);
 ScheduledFuture<V> schedule(Callable<V> callable,long delay, TimeUnit unit);
 ScheduledFuture<?> scheduleAtFixedRate(Runnable command,long initialDelay,long period,TimeUnitunit);
 ScheduledFuture<?> scheduleWithFixedDelay(Runnable command,long initialDelay,long delay,TimeUnitunit);

默認實現為ScheduledThreadPoolExecutor 繼承了ThreadPoolExecutor 的線程池特性,配合future特性,比Timer更強大。 具體用法可以閱讀JDK文檔;spring Task內部也是依靠它實現的。示例代碼:

public static void main(String[] args) {
        ScheduledExecutorService service=Executors.newSingleThreadScheduledExecutor();
        for (int i = 0; i < 10; i++) {
            service.schedule(new Runnable() {
                
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName() + " run ");
                }
            }, 2, TimeUnit.SECONDS);
        }
        service.shutdown();
        
    }
View Code
  • Quartz 定時器實現

Quartz是一個完全由Java編寫的開源作業調度框架,為在Java應用程序中進行作業調度提供了簡單卻強大的機制。Quartz允許開發人員根據時間間隔來調度作業。它實現了作業和觸發器的多對多的關系,還能把多個作業與不同的觸發器關聯。可以動態的添加刪除定時任務,另外很好的支撐集群調度。簡單地創建一個org.quarz.Job接口的Java類,Job接口包含唯一的方法:

public void execute(JobExecutionContext context) throws JobExecutionException;

在Job接口實現類里面,添加需要的邏輯到execute()方法中。配置好Job實現類並設定好調度時間表(Trigger),Quartz就會自動在設定的時間調度作業執行execute()。

整合了Quartz的應用程序可以重用不同事件的作業,還可以為一個事件組合多個作業。Quartz通過屬性文件來配置JDBC事務的數據源、全局作業、觸發器偵聽器、插件、線程池等等。(quartz.properties)

通過maven引入依賴(這里主要介紹2.3.0) 注意:shiro-scheduler中依賴的是1.x版本 如果同時使用會沖突

<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
        <dependency>
            <groupId>org.quartz-scheduler</groupId>
            <artifactId>quartz</artifactId>
            <version>2.3.0</version>
        </dependency>

創建Job類

public class TestJob implements Job{
    @Override
    public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
        println(Thread.currentThread().getName() + " test job begin " + DateUtil.getCurrentTimeStr());
    }
}

調度任務

public static void main(String[] args) throws InterruptedException, SchedulerException {

        Scheduler scheduler = new StdSchedulerFactory().getScheduler();
        // 開始
        scheduler.start();
        // job 唯一標識 test.test-1
        JobKey jobKey = new JobKey("test" , "test-1");
        JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
        Trigger trigger = TriggerBuilder.newTrigger()
                .withIdentity("test" , "test")
                // 延遲一秒執行
                .startAt(new Date(System.currentTimeMillis() + 1000))
                // 每隔一秒執行 並一直重復
        .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever())
                .build();
        scheduler.scheduleJob(jobDetail , trigger);

        Thread.sleep(5000);
        // 刪除job
        scheduler.deleteJob(jobKey);
    }

關於簡單使用,可以參考quartz的example,下面鏈接是一些入門幫助。

Quartz定時任務學習(一)簡單任務 
Quartz定時任務學習(二)web應用 
Quartz定時任務學習(三)屬性文件和jar

深入學習可以閱讀官方文檔和相關博客閱讀 
以下為推薦博客地址 
quartz詳解2:quartz由淺入深  

  • Spring 相關的任務調度

Spring 3.0+ 自帶的任務調度實現,主要依靠TaskScheduler接口的幾個實現類實現。刪除和修改任務比較麻煩。 
主要用法有以下三種: 

    • Spring配置文件實現
    • 注解實現
    • 代碼動態添加
配置文件實現

 

spring-schedule.xml

<task:scheduler id="myScheduler" pool-size="10" />
<task:scheduled-tasks scheduler="myScheduler">
    <task:scheduled ref="job" method="test" cron="0 * * * * ?"/>
</task:scheduled-tasks>

 

注解實現  

 

spring-schedule.xml
<task:scheduler id="myScheduler" pool-size="10" />
// 啟用注解
<task:annotation-driven scheduler="myScheduler"/> 

 

@Component  
public class Task{  

       @Scheduled(cron="0/5 * *  * * ? ")   //每5秒執行一次       
       public void execute(){     
             DateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");    
             System.out.println(sdf.format(DateTime.now().toDate())+"*********B任務每5秒執行一次進入測試");      
       }      
}  

 代碼動態添加 

spring-schedule.xml

<bean id = "myScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
        <property name="poolSize" value="10"/>
        <property name="threadGroupName" value="myScheduler" />
        <property name="threadNamePrefix" value="-1" />
</bean>
<task:annotation-driven scheduler="myScheduler"/> 
@Component
public class Test {

    @Autowired
    private ThreadPoolTaskScheduler myScheduler;

    public void addJob(){

        myScheduler.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + " run ");
            }
        } , new CronTrigger("0/5 * *  * * ? ")); //每5秒執行一次
    }
}

spring 結合 quartz 實現任務調度 

    • spring 配置文件 spring-quartz.xml

 

<bean id="quartzsScheduler" class="org.springframework.scheduling.quartz.SchedulerFactoryBean" lazy-init="false">
        <property name="triggers">
            <list>
            <ref bean="testTrigger" />
            </list>
        </property>
</bean>

<!-- jobClass需要繼承QuartzJobBean  也可以使用 MethodInvokingJobDetailFactoryBean 定義任意類任意方法為Job-->
<bean id="testJobDetail" class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
              <property name="jobClass">
                     <value>com.test.TestJob</value>
              </property>
              <property name="durability" value="true" />
              <!-- requestsRecovery屬性必須設置為 true,當Quartz服務被中止后,再次啟動或集群中其他機器接手任務時會嘗試恢復執行之前未完成的所有任務 -->
              <property name="requestsRecovery" value="true" />
</bean>
<bean id="testTrigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
              <property name="jobDetail" ref="testJobDetail" />
              <property name="cronExpression" value="0 0 10 * * ?" />
</bean>

動態增加刪除  

 

@Component
public class Test {

    @Autowired
    private SchedulerFactoryBean quartzScheduler;

    public void addJob() throws SchedulerException {

        Scheduler scheduler = quartzScheduler.getScheduler();
        JobKey jobKey = new JobKey("test", "test");
        if (scheduler.checkExists(jobKey)) {
            return;
        }
        JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity(jobKey).build();
        Trigger trigger = TriggerBuilder.newTrigger().withIdentity("test", "test")
                .withSchedule(SimpleScheduleBuilder.simpleSchedule().withIntervalInSeconds(1).repeatForever()).build();
        scheduler.scheduleJob(jobDetail, trigger);
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM