自己实现定时器
思路:
1.由于定時器涉及到時間問題。所以在線程執行時需要判斷時間是否允許,而且又是在多線程環境下,所以我們采用優先級阻塞隊列來存取任務。
2.存放的任務我們定義為 MyTimerTask 類,而且要重寫 Comparable 接口來確定優先級。
3.和實現前面的線程池方法類似,我們在創建定時器對象是直接確定線程池的大小和優先級阻塞隊列的大小,并且直接啟動線程。線程的 run 方法也是從優先級阻塞隊列中取任務并運行。
4.創建 schedule 方法,向優先級阻塞隊列中存入任務類。
參考代碼:
import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.PriorityBlockingQueue;public class MyTimerPool {// 優先級阻塞式隊列,存放的元素需要實現Comparable接口// MyTimerTask是根據next下次執行時間比較的,優先獲取next最小的private PriorityBlockingQueue<MyTimerTask> workQueue;// 執行的線程(類似固定線程池)private MyTimerThread[] threads;// 和線程池實現邏輯類似public MyTimerPool(int capacity, int size){this.threads = new MyTimerThread[capacity];workQueue = new PriorityBlockingQueue<>(size);for(int i=0; i<capacity; i++){threads[i] = new MyTimerThread(workQueue);threads[i].start();}}// 執行定時任務public void schedule(Runnable task, long delay, long period){workQueue.put(new MyTimerTask(task, delay, period));// 當前傳入的任務,下次執行時間可能是最小的,所以// 需要通知線程,重新從阻塞隊列中獲取元素synchronized (workQueue){workQueue.notifyAll();}}public static class MyTimerThread extends Thread{private PriorityBlockingQueue<MyTimerTask> workQueue;public MyTimerThread(PriorityBlockingQueue<MyTimerTask> workQueue) {this.workQueue = workQueue;}@Overridepublic void run() {try {while(true){// 阻塞式隊列take()方法是阻塞式的,poll()是非阻塞式MyTimerTask myTimerTask = workQueue.take();long current = System.currentTimeMillis();long next = myTimerTask.next;if(current < next){// 等待下次執行時間到了,或者被通知到synchronized (workQueue){workQueue.wait(next - current);// put()方法是阻塞式的,offer()是非阻塞的workQueue.put(myTimerTask);}} else {Date date = new Date(next);// 打印下次執行時間DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");System.out.println("date="+df.format(date));myTimerTask.task.run();if(myTimerTask.period > 0){myTimerTask.next += myTimerTask.period;workQueue.put(myTimerTask);}}}} catch (InterruptedException e) {e.printStackTrace();}}}public static class MyTimerTask implements Comparable<MyTimerTask>{private long next;// 下次執行時間private Runnable task;private long period;public MyTimerTask(Runnable task, long delay, long period) {this.next = System.currentTimeMillis() + delay;this.task = task;this.period = period;}@Overridepublic int compareTo(MyTimerTask o) {return Long.compare(next, o.next);}}public static void main(String[] args) {MyTimerPool pool = new MyTimerPool(3, 1000);pool.schedule(new Runnable() {@Overridepublic void run() {System.out.println("明天要答辯");}}, 0, 1000);pool.schedule(new Runnable() {@Overridepublic void run() {System.out.println("后天要放假");}}, 1500, 3000);} }總結
- 上一篇: 华为仿真模拟器与VMware虚拟机还能这
- 下一篇: 图片合成gif动画如何在线操作?怎样在线