java定时器Timer 类的使用及Timer already cancelled问题解决

1. Timer和TimerTask

  Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外另起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。

  TimerTask是一个实现了Runnable接口的抽象类,代表一个可以被Timer执行的任务。


2. 一个简单的Timer使用示例

package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
	
	public static void main(String[] args) {
		Timer timer = new Timer();
		timer.schedule(task, 0, 3000);
		
	}
	static TimerTask task = new TimerTask() {
		@Override
		public void run() {
			System.out.println("每3s执行一次");
		}
	};
	
}

执行效果:定时每3秒执行一次任务

取消定时任务只需再调用一次timer.cancel();即可取消任务调度。

package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {

	public static void main(String[] args) throws Exception {
	    Timer timer = new Timer();
		timer.schedule(task, 0, 2000);
		Thread.sleep(10000);
		//取消定时任务
		timer.cancel();
		System.out.println("定时任務已取消");
	}
	
	static TimerTask task = new TimerTask() {
		@Override
		public void run() {
			System.out.println("每3s执行一次");
		}
	};

}

3.关于Timer already cancelled以及Task already scheduled or cancelled问题

3.1问题的原因

当我们使用task.cancel()或者timer..cancel()来取消定时任务后再调用原来的定时任务时,可能会出现这两种错误,原因是因为每个task都是一次性的消耗品,当使用cancel方法后,这个task就被消耗掉了,想要再次使用就只能再次创建新的task,timer也是如此。如下:

3.2 多任务调度

方式一: 

如果有多个定时task要执行,我们可以提供继承TimerTask来分别定义两个task的方法实现。当想要取消某个task,使用task.cancel()来取消指定task,可以将timer设置为全局变量,所有task共用一个timer。

task1:

package com.dswh.test;

import java.util.TimerTask;

public class Task1 extends TimerTask{

	@Override
	public void run() {
		System.out.println("我是task1,每2s执行一次");
	}
	
}

task2: 

package com.dswh.test;

import java.util.TimerTask;

public class Task2 extends TimerTask {
	
	@Override
	public void run() {
		System.out.println("我是task2,每3s执行一次");
	}
	
}

测试:

package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
	
	private static Timer timer = new Timer();

	public static void main(String[] args) throws Exception {
	    //新建task1
		Task1 task1 = new Task1();
		//新建task2
		Task2 task2 = new Task2();
		//调度
		timer.schedule(task1, 0, 2000);
		timer.schedule(task2, 0, 3000);
		Thread.sleep(5000);
		//取消定时任务
		task1.cancel();
		System.out.println("task1 cancel");
		//此时就不能再调用task1了,否则会报Task already scheduled or cancelled
		//想再次调用只能重新new Task1();
		//新建task1
		Task1 task1_1 = new Task1();
		//再次调度
		timer.schedule(task1_1, 0, 2000);
	}
	
}

 

方式二:执行某些定时任务,我们可能需要传递些参数,这时我们可以使用下面这种方式

task1:

package com.dswh.test;

import java.util.TimerTask;

public class Task1{

	public TimerTask  getTask1(String s) {
		return new TimerTask() {
			@Override
			public void run() {
				System.out.println(s);
			}
		};
	}
}

测试:

package com.dswh.test;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
	
	private static TimerTask task = null;
	private static Timer timer = new Timer();

	public static void main(String[] args) throws Exception {
		//开始任务
		startTask("我是传入的参数,执行task1任务");
		Thread.sleep(3000);
		//取消任务
		endTask("任务结束了");
		//再次开启
		Thread.sleep(3000);
		startTask("任务再次开启");
		
	}
	public static void startTask(String s) throws InterruptedException {
		if (task==null) {
			 task = new Task1().getTask1(s);
		}
		timer.schedule(task, 0, 1000);
	}
	
	public static void endTask(String s) {
		task.cancel();
		task=null;
		System.out.println(s);
	}
	
}

 

 

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值