多线程案例3--计时器


很多时候,客户端请求服务器,在发送完请求之后, 一直都等不来服务器响应, 此时客户端不能一直等下去, 此因此客户端就要设置一个"超时时间",也就是说,一旦等待时长超过这个时间, 客户端就会自动执行某一段代码

这里就会用到计时器的实现

标准库中的计时器

计时器主要就是schedule方法

image-20220921113149276

schedule(超时后要执行的方法, 超时时间ms);

这里的TimeTask是一个runnable接口, 所以要new TimeTask(),然后重写run方法, 从而执行操作

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

public class Demo25 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("好好学习!");
            }
        },100);
         System.out.println("开始计时!");
    }
}

Timer也能执行多个任务

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

public class Demo25 {
    public static void main(String[] args) {
        Timer timer = new Timer();
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("好好学习!");
            }
        },100);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("赶紧学习!");
            }
        },200);
        timer.schedule(new TimerTask() {
            @Override
            public void run() {
                System.out.println("快快快!");
            }
        },300);
        System.out.println("开始计时!");

    }
}

image-20220921114113691

值得注意的是: 执行完任务之后, 进程并没有结束

原因就是Timer内部需要一组线程来执行注册的任务, 这里的线程是前台线程, 会影响进程退出

后台线程 vs 前台线程

isDaemon 要是true就是后台线程(守护线程),不会影响进程退出,直接就把进程销毁了

要是isDaemon是false,就是前台线程,就会影响进程退出

自己实现定时器

import java.util.PriorityQueue;
//实现自己的定时器
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.PriorityBlockingQueue;

class MyTask implements  Comparable<MyTask>{
    private Runnable runnable;
    private long time;
    public MyTask(Runnable runnable, long delay) {
        this.runnable  = runnable;
        this.time = System.currentTimeMillis() + delay;
    }

    public Runnable getRunnable() {
        return runnable;
    }

    public long getTime() {
        return time;
    }

    @Override
    public int compareTo(MyTask o) {
        return (int)(this.time - o.time);//time是long类型,compareTo接口要是int的,所以要强转
    }
}

class MyTimer{
    //使用优先级阻塞队列 既保证了按照时间优先级来调用,又保证了线程安全
    private BlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    Object locker = new Object();
    public  MyTimer(){
        //创建一个线程,不停的扫描队列中的队首元素,时间一到就执行任务
        Thread t = new Thread(()->{
            //但是,这个循环会一直执行,一直都在看时间,就会浪费效率,也就是"忙等"
            //使用wait来解决
           while(true) {
               synchronized (locker) {
                   try {
                       //取出队首元素
                       MyTask myTask = queue.take();
                       long curTime = System.currentTimeMillis();
                       if (myTask.getTime() <= curTime) {
                           //到点了,该执行任务了
                           myTask.getRunnable().run();
                       } else {
                           //还没到点就再塞会阻塞优先级队列里面
                           //还没到点就等待
                           locker.wait(myTask.getTime()-curTime );
                           queue.put(myTask);
                       }
                   } catch (InterruptedException e) {
                       e.printStackTrace();
                   }
               }
           }
        });
        t.start();
    }
    public  void schedule(Runnable runnable, long after) throws InterruptedException {
        MyTask myTask = new MyTask(runnable, after);
        queue.put(myTask);
        //要是有新的时间添加进来,就唤醒,并且调整wait的时间
        synchronized (locker) {
            locker.notify();
        }
    }
}
public class Demo26 {
    public static void main(String[] args) throws InterruptedException {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("快点行动1");
            }
        },1000);
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("快点行动2");
            }
        },2000);
        System.out.println("计时开始");
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值