Java定时器(一)Timer和TimerTask
方式一:设定指定任务task在指定时间time执行 schedule(TimerTask task, Date date)
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("………这里是逻辑代码………"); } }, 5000,5000); while(true){ Thread.sleep(1000); System.out.println(new Date().getSeconds()); } }
此代码的结果是5秒后输出"……这里是逻辑代码……"
方式二:设定指定任务task在指定延迟delay后进行固定延迟peroid的执行 schedule(TimerTask task,long delay,long period)
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("……这里是逻辑代码……"); } },new Date(), 5000); while(true){ Thread.sleep(1000); System.out.println(new Date().getSeconds()); } }
此段代码输出结果为延迟5秒后,每隔5秒输出"……这里是逻辑代码……"
方式三:设定指定任务task在指定开始时间firstTime开始后进行固定频率peroid的执行 schedule(TimerTask task,Date firstTime,long period)
public static void main(String[] args) throws Exception { // TODO Auto-generated method stub new Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("……这里是逻辑代码……"); } },new Date(), 5000); while(true){ Thread.sleep(1000); System.out.println(new Date().getSeconds()); } }
这里的代码输出结果为在当前时间开始后马上输出"……这里是逻辑代码……",之后每隔5秒输出"……这里是逻辑代码……"
1. DelayQueue延时队列操作实例
DelayQueue延时队列,当队列中的元素到达延迟时间时才会被取出。队列元素会按照最终执行时间在队列中进行排序。
最近刚学,本篇先给出一个实际使用的例子。
首先队列对象当然就是DelayQueue。而队列元素则需要实现Delayed这个接口,并实现该接口compareTo方法和getDelay方法。
首先定义该元素及其属性。
class DelayTask implements Delayed {
public String name;
public Long delayTime;
public TimeUnit delayTimeUnit;
public Long executeTime;//ms
DelayTask(String name, long delayTime, TimeUnit delayTimeUnit) {
this.name = name;
this.delayTime = delayTime;
this.delayTimeUnit = delayTimeUnit;
this.executeTime = System.currentTimeMillis() + delayTimeUnit.toMillis(delayTime);
}
}
getDelay方法的作用即是计算当前时间到执行时间之间还有多长时间。
如下,返回unit单位下该延迟时间的值。
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
compareTo方法的作用即是判断队列中元素的顺序谁前谁后。当前元素比队列元素后执行时,返回一个正数,比它先执行时返回一个负数,否则返回0.
@Override
public int compareTo(Delayed o) {
if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) {
return 1;
}else if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) {
return -1;
}
return 0;
}
最后我们用个简单的方法测试下:
public static void main(String[] args) {
DelayQueue<DelayTask> queue = new DelayQueue<>();
queue.add(new DelayTask("1", 1L, TimeUnit.SECONDS));
queue.add(new DelayTask("2", 2L, TimeUnit.SECONDS));
queue.add(new DelayTask("3", 3L, TimeUnit.SECONDS));
System.out.println("queue put done");
while(!queue.isEmpty()) {
try {
DelayTask task = queue.take();
System.out.println(task.name + ":" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
运行结果如下:
queue put done
1:1504498317145
2:1504498318145
3:1504498319145
下面是完整的代码:
public class DelayQueueTest {
public static void main(String[] args) {
DelayQueue<DelayTask> queue = new DelayQueue<>();
queue.add(new DelayTask("1", 1000L, TimeUnit.MILLISECONDS));
queue.add(new DelayTask("2", 2000L, TimeUnit.MILLISECONDS));
queue.add(new DelayTask("3", 3000L, TimeUnit.MILLISECONDS));
System.out.println("queue put done");
while(!queue.isEmpty()) {
try {
DelayTask task = queue.take();
System.out.println(task.name + ":" + System.currentTimeMillis());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class DelayTask implements Delayed {
public String name;
public Long delayTime;
public TimeUnit delayTimeUnit;
public Long executeTime;//ms
DelayTask(String name, long delayTime, TimeUnit delayTimeUnit) {
this.name = name;
this.delayTime = delayTime;
this.delayTimeUnit = delayTimeUnit;
this.executeTime = System.currentTimeMillis() + delayTimeUnit.toMillis(delayTime);
}
@Override
public int compareTo(Delayed o) {
if(this.getDelay(TimeUnit.MILLISECONDS) > o.getDelay(TimeUnit.MILLISECONDS)) {
return 1;
}else if(this.getDelay(TimeUnit.MILLISECONDS) < o.getDelay(TimeUnit.MILLISECONDS)) {
return -1;
}
return 0;
}
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(executeTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
}
2. 定时任务轮询数据库
3. redis 优雅关闭超时订单
public class RedisUtil{ private JedisPool jedisPool; //生产一个任务 public void addItem(String key,long score,String member){ Jedis redis = jedisPool.getResource(); redis.zadd(key,score,member); } //发现超时任务 public void getItem(String key){ Jedis redis= jedisPool.getResource(); while(true){ Set<Tuple> itemSet = redis.zrangeWithScores(key,0,0); if(itemSet==null){Thread.sleep(1000); continue;} double score=((Tuple)itemSet.toArray()[0]).getScore(); String element=((Tuple)itemSet.toArray()[0]).getElement(); double currentTime = CalendarUtils.getCurrentTimeInMillis(0); if(currentTime>=score){ redis.zrem(key,element); } } } }