【javaEE】多线程初阶(Part7定时器)!!


前言

今天不学习,明天变垃圾

本文内容主要是:多线程实例的【定时器】,定时器的实现其实是比较复杂的,建议一定要自己尝试写一遍并进行理解,多线程这块儿很重要。


一、定时器简介

  1. 定时器就类似于闹钟。而代码中的定时器,通常是设定多长时间之后来执行某个动作(其实也就是具体的代码逻辑)
  2. 在具体的服务器开发中,客户端向服务器端发送请求之后就需要等待服务器端的响应,但是服务器端的响应时间是不确定的。
  3. 如果出现了客户端等待很久而服务器端依旧不响应的情况,客户端是不会死等下去的,如果一直死等下去,程序很可能就会卡死;因此客户端经常会设置一个“超过时间”,此时就使用定时器来实现。

二、 标准库中的定时器Timer

  1. 标准库中的定时器 Timer类(使用的是java.util中的)。
  2. 而在Timer类中的一个重要的方法是schedule(TimerTask task, long delay)
    ① 参数1 TimerTask task是要安排的任务,其实就是一个Runnable接口,我们要做的就是继承这个TimerTask,然后重写run方法,从而指定要执行的任务。【注意!参数1是 new TimerTask() {…重写run方法},不是new Runnable() {…}】
    ② 参数2 long delay 就是指经过delay (ms)之后开始执行参数1任务task。
  3. 一个定时器可以同时安排多个任务!
  4. 执行代码会发现,在执行完task任务之后进程并没有退出,理由:Timer内部需要一组线程来执行注册的任务task,而这里的线程是前台线程,会影响进程退出。
  5. 【标准库实现】 参考代码:Demo3标准库实现定时器

三、模拟实现定时器(难!)

  1. 自己实现【定时器Timer】
    1)创建一个类MyTimer,实现schedule方法,该方法中有两个参数,参考标准库中的schedule方法,一个参数是TimerTask task,一个参数是long delay
    2)写一个类MyTask来描述两个参数,该类要能够描述【任务信息以及什么时候执行该任务】。(尤其要注意执行时间time的赋值!!)
  2. 如何让MyTimer管理多个任务(标准类中的Timer类是可以管理多个任务的)?直接使用ArrayList来存储多个任务行不行?
    答:1)No。任务是有执行时间的,设置的时间越短的任务越要先执行。但是如果使用ArrayList的话元素的存储是无序的,找到时间最小的任务其实是不太方便的(遍历是需要花费时间的,时间复杂度O(N),在任务较多时就是不太方便的)
    2)所以:使用【优先队列:无论你按照什么顺序插入,出队列的顺序其实是固定的】。但是线程不安全,而schedule可能在多线程中调用。所以,为了保证线程安全,可以使用阻塞队列
    (因为BlockingQueue是一个接口,所以在实例化的时候就new 一个构造方法,该构造方法就用PriorityBlockingQueue()优先级阻塞队列 来实现)
  3. 【任务被安排到优先级阻塞队列中了,接下来就需要从队列中取元素了:创建一个单独的扫描线程,让这个线程不停的来检查队首元素时间是否到了,如果时间到了则执行该任务。】
  4. 由于阻塞队列无法阻塞式的取队首元素,所以:只能先取出任务再判定任务时间是否到了;如果时间没到就再把任务放回去
  5. 因为优先级队列进行存储元素的时候需要按照一定的比较规则,则此时应该在MyTask类中继承Comparable接口来重写compareTo方法规定比较方法,进而达到有序存储元素
    (还存在 【忙等】问题,使用wait和notify方法,注意要加锁以及wait的等待时间,以及同一对象!)
  6. 【多线程其实是比较复杂的,但是在cpp和java中多线程仍然是最基本的并发编程方式,一定要克服这个难关!!】
  7. 参考代码:Demo4
    Demo4真的重要!!!建议自己写一遍!
    面试题中多线程超级多!!重要!!
  8. 小结定时器实现:
    ① MyTimer 类提供的核心方法为 schedule, 用于注册一个任务, 并指定这个任务多长时间后执行。
    ② MyTask 类用于描述一个任务, 里面包含一个 Runnable 对象和一个 time(毫秒时间戳)
    这个对象需要放到 优先队列 中, 因此需要实现 Comparable 接口。
    ③ MyTimer 实例中, 通过 PriorityBlockingQueue 来组织若干个 MyTask 对象,
    通过 schedule 来往队列中插入一个个 MyTask 对象。
    ④ MyTimer 类中存在一个扫描线程, 一直不停的扫描队首元素, 看看是否能执行这个任务。(所谓 “能执行” 指的是该任务设定的时间已经到达了)
    ⑤ 引入一个对象, 借助该对象的 wait / notify 来解决 while (true) 的忙等问题(也就是不停扫描,浪费CPU)
    修改 扫描线程 的 run 方法, 引入 wait, 等待一定的时间;
    修改 MyTimer 的 schedule 方法, 每次有新任务到来的时候唤醒一下 扫描 线程. (因为新插入的任务可能是需要马上执行的)。

THINK

  1. 多线程在面试中常考!!
  2. 定时器的模拟实现一定要自己能够写!!
  3. 注意定时器的实现逻辑。
  4. 定时器中重要的方法是schedule。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

'Dream是普通小孩耶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值