码迷,mamicode.com
首页 > 编程语言 > 详细

跟着实例学习java多线程9-定时任务实例

时间:2015-02-07 01:44:11      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:

定时任务是我们经常遇到的业务场景,我们有很多的功能都需要这样的技术来实现,例如:定时获取一些数据push出去,定时处理一些清理任务,定时检查某个值等。那么我们该怎么实现,在实现中又该注意一些什么?

定时任务就是另开一个线程来执行,其实也是并发的一类,大家可能不好理解,说定时不就是到时间执行一下,怎么还会产生并发,这里主要是看两个指标,一是看执行频率,二是看每次执行的时间,如果执行频率高并且执行任务又会很耗时,那么这时候就形成了并发,当然还有一种情况那就是,定时的job中调用其它服务的方法,而正常的业务逻辑中也调用那个服务的方法,那么这时在某个巧合的时间也有可能发生并发。

所以我们在写定时任务的时候也要注意这么两点:

1:如果执行频率高并且执行任务又会很耗时,要在job的执行方法上加同步处理。

2:如果job里调用其它服务方法,那么其它服务所提供的方法也要保证发布成线程安全的方法。

下面我们来说一下有几种实现定时任务的方法:

1:java提供的timer

package com.home.thread.thread10;

import java.util.Date;
import java.util.Timer;

/**
 * @author gaoxu
 * 实践出真知!
 */
public class TimerMain {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Timer timer = new Timer();
		timer.schedule(new TimerTaskThread(), new Date(), 2000);
	}

}


package com.home.thread.thread10;

import java.util.Date;
import java.util.TimerTask;

/**
 * @author gaoxu
 * 实践出真知!
 */
public class TimerTaskThread extends TimerTask{
	//没有参数的构造函数
	public TimerTaskThread(){
		
	}
	//也可以写有参数的构造函数

	@Override
	public synchronized void run() {
		System.out.println(new Date().toString()+"Timer方式,我是两秒执行一次");
		//这里可以写自己要实现的定时业务
		
	}

}

这是一个由timer来实现的定时任务,运行结果如下:

Sat Feb 07 01:25:31 CST 2015,Timer方式,我是两秒执行一次
Sat Feb 07 01:25:33 CST 2015,Timer方式,我是两秒执行一次
Sat Feb 07 01:25:35 CST 2015,Timer方式,我是两秒执行一次
Sat Feb 07 01:25:37 CST 2015,Timer方式,我是两秒执行一次

2:由开源框架Quartz实现的定时任务

package com.home.thread.thread10;

import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;

import com.home.JobServiceImpl;

/**
 * @author gaoxu
 * 实践出真知!
 */
public class SchedulerMain {
	public static void main(String[] para) {
		
		try {
			SchedulerFactory sf = new StdSchedulerFactory();
			Scheduler scheduler = sf.getScheduler();
			JobServiceImpl jobService = new JobServiceImpl();
			jobService.setScheduler(scheduler);
			jobService.platDataCollectInterval(2);
		} catch (SchedulerException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

}


package com.home;

import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SimpleScheduleBuilder;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;

import com.home.job.TestJob;


/**
 * @author gaoxu
 * 实践出真知!
 */
public class JobServiceImpl {

	private Scheduler scheduler;

	public void setScheduler(Scheduler scheduler) {
		this.scheduler = scheduler;
	}

	public Scheduler getScheduler() {
		return scheduler;
	}

	public void platDataCollectInterval(int interval)
			throws SchedulerException, Exception {
		System.out.println("update  PlatDataCollect cycle start");

		JobDetail jobDetail = JobBuilder.newJob(TestJob.class).withIdentity("testJob_1", "group_1").build();

		Trigger trigger = TriggerBuilder
				.newTrigger()
				.withIdentity("trigger_1", "group_1")
				.withSchedule(
						SimpleScheduleBuilder
								.repeatSecondlyForever(interval)).build();

		scheduler.scheduleJob(jobDetail, trigger);

		scheduler.start();

	}

}

package com.home.job;

import java.util.Date;

import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;

public class TestJob implements Job{

	@Override
	public void execute(JobExecutionContext arg0) throws JobExecutionException {
		 System.out.println("test job date:" + new Date().toString());  
		
	}

}


这里有三个类,其中job类是任务的执行者,Scheduler是一个调度器,调度器中可以创建多个Trigger,每个Trigger可以执行一个job。

log4j:WARN No appenders could be found for logger (org.quartz.impl.StdSchedulerFactory).
log4j:WARN Please initialize the log4j system properly.
log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info.
update  PlatDataCollect cycle start
test job date:Sat Feb 07 01:30:31 CST 2015
test job date:Sat Feb 07 01:30:33 CST 2015
test job date:Sat Feb 07 01:30:35 CST 2015
test job date:Sat Feb 07 01:30:37 CST 2015


3:是线程来实现

package com.home.thread.thread10;

/**
 * @author gaoxu
 * 实践出真知!
 */
public class ThreadMain {
	public static void main(String[] para) {
		ThreadTask threadTask = new ThreadTask();
		threadTask.start();
	}

}



package com.home.thread.thread10;

import java.util.Date;

public class ThreadTask extends Thread{
	
	public void run(){
		while(true){
			try {
				Thread.sleep(2000);
				System.out.println(new Date().toString()+"线程方式,我是两秒执行一次");
				//这里可以写自己要实现的定时业务
			} catch (InterruptedException e) {
				
				e.printStackTrace();
			}
			
		}
	}
}


运行结果:

Sat Feb 07 01:33:34 CST 2015线程方式,我是两秒执行一次
Sat Feb 07 01:33:36 CST 2015线程方式,我是两秒执行一次
Sat Feb 07 01:33:38 CST 2015线程方式,我是两秒执行一次
Sat Feb 07 01:33:40 CST 2015线程方式,我是两秒执行一次
Sat Feb 07 01:33:42 CST 2015线程方式,我是两秒执行一次


还有很多方式可以实现工作任务,例如java.util.concurrent.ScheduledThreadPoolExecutor,这里就不在举例。

一定要注意定时任务的并发性,避免发生并发错误。





跟着实例学习java多线程9-定时任务实例

标签:

原文地址:http://blog.csdn.net/andy_gx/article/details/43588001

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!