java并发编程第四章线程执行器(3)

6.在执行器中延时执行任务
  前面两篇博客都是创建执行器之后启动任务会马上执行,这里如果不想让任务马上被执行,
  而是想让任务在过一段时间后才被执行,或者任务能够被周期性地执行。可以使用执行器框架提供的
 ScheduledThreadPoolExecutor类
这里推荐利用Executors工厂类来创建,定时执行器。使用Executors工厂的newScheduledThreadPool()方法创建该实例对象。方法中的一个参数就是线程池中拥有的线程数量,。
  在定时起中等待一段给定的时间后执行一个任务,需要使用schedule()方法,这个方法接收如下参数
    1.即将执行的任务
    2.任务执行前所要等待的时间。
    3.等待时间的单位,由TimeUnit类的一个常量来指定。
    备注:
    1.如果想在一个给定的时间点来定时执行任务,那就需要计算这个给定时间点和当前时间的差异值,然后用这个差异值作为任务的延迟值。
    2.也可以使用Runnable接口来实现任务,因为ScheduledThreadPoolExecutor类的Schedule()方法可以同时接受这两种类型的任务。
    3.在调用shutdown方法而仍有待处理的任务需要执行时,可以配置ScheduledThreadPoolExecutor的行为。默认的行为是不论执行器是否结束,待处理的任务都将被执行。
    但是通过调用该类的setExecuteExistingDelayedTasksAfterShutdownPolicy方法则可以改变这个行为。传递false参数给这个方法,执行shutdown()方法后待处理的任务将不再执行。

实例代码

/**
 * 
 * @author fcs
 * @date 2015-5-5
 * 描述:在执行器中延迟执行任务
 * 说明:
 */
public class Task implements Callable<String> {

	private String name;
	
	public Task(String name) {
		this.name = name;
	}

	@Override
	public String call() throws Exception {
		System.out.printf("%s: Starting at: %s\n",name,new Date());
		return "return hello world";
	}
}

2.测试类

/**
 * 
 * @author fcs
 * @date 2015-5-5
 * 描述:ScheduledThreadPoolExecutor:可以让任务在过一段时间后才被执行,或者任务能够被周期性的执行。
 */
public class Main {
	public static void main(String[] args) {
		
		ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor)Executors.newScheduledThreadPool(1);
		System.out.printf("Main: Starting at: %s\n",new Date());
		for(int i =0;i< 5;i++){
			Task task = new Task("Task"+i);
			//通过该方法启动这些任务
			executor.schedule(task, i+1, TimeUnit.SECONDS);
		}
		executor.shutdown();
		try {
			//通过该方法等待所有任务完成
			executor.awaitTermination(1, TimeUnit.DAYS);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.printf("Main: Ends at: %s\n",new Date());
	}
}

7.在执行器中周期性执行任务
      有时候任务需要周期性的执行,就需要使用ScheduledThreadPoolExecutor类来执行周期性的任务。
      先需要创建一个ScheduledExecutorService对象。同创建执行器一样,在java中推荐使用Executors工厂类来创建ScheduledExecutorService对象。
      Executors类就是执行器对象的工厂
      。在本范例中使用scheduledAtFixedRate()方法发送任务。这个方法接收4个参数,分别为将被周期性执行的任务,任务第一次执行后的延时时间,
      两次执行的时间周期,以及第二第三个参数的单位。
      需要注意的是,两次执行之间的周期是指任务在两次执行开始时的时间间隔。
      scheduleAtFixedRate()方法返回一个ScheduledFuture对象,ScheduleFuture接口扩展了Future接口,带有定时任务相关的操作方法。ScheduledFuture是一个
      泛型参数化的接口。在该范例中,任务是Runnable对象,并没有泛型参数化,必须通过?符号作为参数来泛型化。
      可以使用ScheduledFuture接口中的一个方法,getDelay()方法返回任务到下一次执行时锁要等待的剩余时间。这个方法接收一个TimeUnit常量作为时间单位。

  实例代码:
1

/**
 * 
 * @author fcs
 * @date 2015-5-6
 * 描述:在执行器中周期性执行任务
 * 说明:使用ScheduledThreadPoolExecutor类来周期性的执行任务
 */
public class Task implements Runnable{

	private String name;
	
	public Task(String name) {
		this.name = name;
	}

	@Override
	public void run() {
		System.out.printf("%s:Starting at: %s\n",name,new Date());
	}
}
2.Main测试类

public class Main {
	public static void main(String[] args) {
		ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
		System.out.printf("Main: Starting at: %s\n",new Date());
		Task task = new Task("Task");
		/**
		 * 参数说明
		 * 1.要执行的任务
		 * 2.首次执行的延迟时间
		 * 3.连续执行之间的周期
		 * 4. 2,3时间参数的单位
		 */
		ScheduledFuture<?>  result = executor.scheduleAtFixedRate(task, 1, 2,TimeUnit.SECONDS);
		
		for(int i =0 ;i< 10;i++){
			System.out.printf("Main: Delay: %d\n",result.getDelay(TimeUnit.MILLISECONDS));
			try {
				TimeUnit.MILLISECONDS.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		
		executor.shutdown();
		
		try {
			TimeUnit.SECONDS.sleep(5);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.printf("Main: Finished at: %s\n",new Date());
	}
}












评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值