schedule的原理:
使用(線程安全)延遲隊列,按照任務的待運行時間從小到大排序,處理schedule的線程不停的從延遲隊列中取任務,只有task任務的待執行時間爲當前時間時,方可取出task執行,其他場景線程進入等待狀態。
瞭解到schedule原理後,嘗試動手寫個小Demo吧!
列出我們需要實現的內容列表:
- 使用JDK自帶延遲隊列的實現(DelayQueue)
- 創建任務類(需要實現Delayed,因爲DelayQueue的元素需強制繼承Delayed類)
- 開啓一個單線程,取出並執行延遲隊列裏的任務
- 創建任務的實例,將實例放入延遲隊列中
- 運行代碼
1、創建任務類DelayTask,實現Delayed類
import lombok.Data;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;
@Data
public class DelayTask implements Delayed {
private long triggerTime;
private Runnable task;
//private boolean cancel;
public DelayTask(long triggerTime, Runnable task) {
this.triggerTime = triggerTime + System.currentTimeMillis();
this.task = task;
}
//獲取任務剩餘執行時間
@Override
public long getDelay(TimeUnit unit) {
return unit.convert(triggerTime - System.currentTimeMillis(), TimeUnit.NANOSECONDS);
}
// 比較方法,用於延遲隊列的排序
@Override
public int compareTo(Delayed o) {
DelayTask o2 = (DelayTask) o;
if (this.triggerTime > o2.getTriggerTime()) {
return 1;
}
if (this.triggerTime < o2.getTriggerTime()) {
return -1;
}
return 0;
}
}
2、開啓線程,往隊列中取出任務,並執行
import lombok.Data;
import java.util.concurrent.DelayQueue;
/**
* @author lpp
*/
@Data
public class ThreadPool implements Runnable {
private DelayQueue<DelayTask> queue;
public ThreadPool(DelayQueue<DelayTask> queue) {
this.queue = queue;
}
@Override
public void run() {
try {
while (true) {
DelayTask delayTask = queue.take();
Runnable task = delayTask.getTask();
task.run();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
3、創建任務實例,放入隊列中,並執行代碼
import lombok.Data;
import java.util.concurrent.DelayQueue;
@Data
public class Execute {
private static DelayQueue<DelayTask> queue = new DelayQueue<>();
public static void createSchedule(Runnable runnable, long delayTime) {
queue.offer(new DelayTask(delayTime, runnable));
}
public static void main(String[] args) {
new Thread(new ThreadPool(queue)).start();
createSchedule(() -> System.out.println("XXXX-task1"), 3000);
createSchedule(() -> System.out.println("XXXX-task2"), 1000);
}
}