数据结构-堆
满二叉树:

完全二叉树:
除了最后一层都达到最大节点数。
小顶堆/大顶堆:
每个值都要比父节点大,最小的在上面。/每个值都要比父节点小,最大的在上面。
堆:


二叉树一般存在数字中,因为可以通过计算快速获取父节点的下标。
存储的顺序为从上往下,从左往右。第一个位置空出来
想要知道某个节点的父节点是谁就用该节点除以2。
例子:
想要知道“8”的父节点(5),就用8在数组中的下标“5”除以2
5/2=2
插入元素
插入尾部,然后上浮
插入尾部:
例如在末尾插入“2”
然后上浮:
将“2”和父节点对比,如果比父节点小,那么交换位置。

然后再交换直到不能再交换

删除堆顶元素
将尾部元素放到堆顶,然后下沉。
1. 顶端元素删除后,把最后的元素放到堆顶。

2.下沉,和子元素作比较。跟最小的元素交换。以此类推

时间轮:

使用timer进行定时任务。
主方法:
package com.tuling.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();//任务启动
for (int i=0;i<2;i++){
TimerTask task = new FooTimerTask("Foo"+i);
t.schedule(task, new Date(),2000);//任务添加
}
}
}
class FooTimerTask extends TimerTask{
private String name;
public FooTimerTask(String name) {
this.name = name;
}
public void run(){
try {
System.out.println("name "+ name+" start time= "+new Date());
Thread.sleep(3000);
System.out.println("name "+ name+" end time= "+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}TimerTask
package com.tuling.timer;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String[] args) {
Timer t = new Timer();//任务启动
for (int i=0;i<2;i++){
TimerTask task = new FooTimerTask("Foo"+i);
t.schedule(task, new Date(),2000);//任务添加
}
}
}
class FooTimerTask extends TimerTask{
private String name;
public FooTimerTask(String name) {
this.name = name;
}
public void run(){
try {
System.out.println("name "+ name+" start time= "+new Date());
Thread.sleep(3000);
System.out.println("name "+ name+" end time= "+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}这样会丢任务,因为是单线程所以会有任务阻塞。
Cron表达式

通用符号:
, : 表示列出枚举值。例如:在Minutes域使用5,20,表示在时间的分钟数为5、20时触发事件
- : 表示范围。例如在Minutes域使用5-20,表示在时间的分钟数为5到20时每分钟都触发事件
* : 表示匹配该域的任意值。假如在Minutes域使用*,表示时间分钟数不做限制,每分钟都触发事件
/ : 表示起始时间开始触发,然后每隔固定时间触发一次。例如在Minutes域使用5/20,表示时间的分 钟数为5时触发一次,后隔20分钟即25、45再分别触发一次事件。
例子:
0 10,44 14 ? 3 WED
每年的,3月的,每个周三的,14点,10分和44分的,0秒。执行任务
专有符号:
? : 只能用在DayofMonth和DayofWeek两个域,由于DayofMonth和DayofWeek互斥,须对其一设 置?(星期几和日期,只能设置一个)
L : 表示最后,只能出现在DayofWeek和DayofMonth域。如果在DayofWeek域使用5L ,意味着在最后的—个星期四触发
W:表示有效工作日(周一到周五),只能出现在DayofMonth域,系统将在离指定日期的最近的有效工 作日触发事件。(例如“5W”,就是5号离工作日最近的日子。假如5号是周日,那么5W就是周 一)
LW : 这两个字符可以连用,表示在某个月最后一个工作日
# : 用于确定每个月第几个星期几,只能出现在DayofWeek域。例如在4#2,表示某月的第二个星 期三
C : 只能用在DayofMonth和DayofWeek两个域,需要关联日历,如果没关联可以忽略。
专有符号中除?外,在Spring定时任务中都不支持!
异步多线程:
开启多线程
@EnableAsync
在每个任务前添加注解,来使其变成多线程
@Async
package com.javaeelearn.schedule;
import javafx.scene.input.DataFormat;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import java.text.DateFormat;
import java.util.Date;
@EnableScheduling
@EnableAsync
@SpringBootApplication
public class ScheduleApplication {
public static void main(String[] args) {
SpringApplication.run(ScheduleApplication.class, args);
}
//每半个小时提醒一次
@Async
@Scheduled(fixedRate = 3*1000)
public void playSth(){
System.out.println("线程"+Thread.currentThread().getName());
System.out.println("发微信"+ DateFormat.getDateTimeInstance().format(new Date()));
}
//四小时提醒一次
@Async
@Scheduled(fixedRate = 10*1000)
public void playSth2(){
System.out.println("线程"+Thread.currentThread().getName());
System.out.println("玩游戏"+ DateFormat.getDateTimeInstance().format(new Date()));
}
}