定时器(标准库&自己设计)

join(指定超时时间)sleep(指定休眠时间)

一.标准库的定时器

核心:schedule,参数有两个①任务②多长时间之后执行

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

public class Demo3 {
    public static void main(String[] args) {
        Timer timer=new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        },3000);
        System.out.println("main");
    }
}

先打印main,3秒钟之后打印hello

二.自己实现一个定时器

Timer:

①描述任务:创建一个专门的类来表示定时器的任务

class MyTask{
    //创建一个具体事件
    public  Runnable runnable;
    //创建执行任务的时间戳
    public long time;
    
    public MyTask(Runnable runnable,long after) {
        this.runnable = runnable;
        this.time=System.currentTimeMillis()+after;
    }
    public void run(){
        runnable.run();
    }
}

②组织任务:通过数据结构组织

在标准库中有一个专门的数据结构:PriorityBlockingQueue(有优先级,又有阻塞队列)

 遇到了一个问题:优先队列里面是堆,但是每个类之间的大小关系不明确。myTask的比较规则不存在,需要手动指定,按照时间大小来比较。编译器在比较的时候尝试把这些类往comparable转换来比较,但是转换失败。

//改进:加接口
class MyTask implements Comparable<MyTask>{
    //创建一个具体事件
    public  Runnable runnable;
    //创建执行任务的时间戳
    public long time;

    public MyTask(Runnable runnable,long after) {
        this.runnable = runnable;
        this.time=System.currentTimeMillis()+after;
    }
    public void run(){
        runnable.run();
    }
    public long getTime(){
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        return (int) (this.time-o.time);
    }
}

③执行时间到了的任务

class MyTimer{
    private PriorityBlockingQueue<MyTask> queue=new PriorityBlockingQueue<>();
    public void schedule(Runnable runnable,long delay){
        MyTask task =new MyTask(runnable,delay);
        queue.put(task);
    }

    public MyTimer(){
        //在线程里面不断扫描
        Thread thread=new Thread(() -> {
            while (true) {
                try {
                    //取出队首元素
                    MyTask task = queue.take();

                    //取当前时间
                    long curTime = System.currentTimeMillis();
                    if (curTime < task.getTime()) {
                        //比较,如果时间没到,把任务塞回队列
                        queue.put(task);
                    } else {
                        //如果时间到了,则执行任务
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }
}

第二个问题:如果队列中的任务为空,则线程阻塞;若队列中的任务不空且任务时间没到

wait能被中途唤醒;sleep中途不能被唤醒

package Thread;

import java.util.PriorityQueue;
import java.util.concurrent.PriorityBlockingQueue;

//创建一个类表示一个任务
class MyTask implements Comparable<MyTask>{
    //创建一个具体事件
    public  Runnable runnable;
    //创建执行任务的时间戳
    public long time;

    public MyTask(Runnable runnable,long after) {
        this.runnable = runnable;
        this.time=System.currentTimeMillis()+after;
    }
    public void run(){
        runnable.run();
    }
    public long getTime(){
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        return (int) (this.time-o.time);
    }
}
class MyTimer{
    private PriorityBlockingQueue<MyTask> queue=new PriorityBlockingQueue<>();
    public void schedule(Runnable runnable,long delay){
        MyTask task =new MyTask(runnable,delay);
        queue.put(task);
    }

    public MyTimer(){
        //在线程里面不断扫描
        Thread thread=new Thread(() -> {
            while (true) {
                try {
                    //取出队首元素
                    MyTask task = queue.take();

                    //取当前时间
                    long curTime = System.currentTimeMillis();
                    if (curTime < task.getTime()) {
                        //比较,如果时间没到,把任务塞回队列
                        queue.put(task);
                    } else {
                        //如果时间到了,则执行任务
                        task.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        thread.start();
    }
}

public class Demo3 {
    public static void main(String[] args) {
        MyTimer myTimer=new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        },3000);
        System.out.println("main");
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值