介绍Timer是实际应用中非常常用和有效的工具。它的原理是将要执行的任务按照执行时间的先后顺序排序,然后在特定的时间执行。JAVA提供了java.util.Timer、java.util.concurrent.ScheduledThreadPoolExecutor等多种Timer工具,但是这些工具在执行效率上还是存在一些缺陷,所以netty提供了HashedWheelTimer,一个优化的Timer类。下面我们来看看netty的Timer有什么区别。java.util.TimerTimer是JAVA在1.3引入的。所有任务都存储在里面的TaskQueue中:privatefinalTaskQueuequeue=newTaskQueue();TaskQueue底层是一个TimerTask数组,用来存放要执行的任务。私人TimerTask[]queue=newTimerTask[128];看起来TimerTask只是一个数组,但是Timer让这个队列变成了一个平衡的二叉堆。添加TimerTask时,会插入到Queue的尾部,然后调用fixup方法重新平衡:voidadd(TimerTasktask){//Growbackingstoreif(size+1==queue.length)queue=Arrays.copyOf(queue,2*queue.length);队列[++大小]=任务;修正(大小);当正在运行的任务从堆中移除时,将调用fixDown方法进行重新平衡:voidremoveMin(){queue[1]=queue[size];队列[大小--]=null;//删除额外的引用以防止内存泄漏fixDown(1);fixup的原理是比较当前节点和它的父节点,如果比父节点小,就和父节点交互,然后遍历这个过程:privatevoidfixUp(intk){while(k>1){整数j=k>>1;如果(队列[j].nextExecutionTime<=队列[k].nextExecutionTime)中断;TimerTasktmp=queue[j];队列[j]=队列[k];队列[k]=tmp;k=j;fixDown的原理是比较当前节点与其子节点,如果当前节点大于子节点,则降级:privatevoidfixDown(intk){intj;而((j=k<<1)<=大小&&j>0){如果(j<大小&&queue[j].nextExecutionTime>queue[j+1].nextExecutionTime)j++;//j索引最小的孩子if(queue[k].nextExecutionTime<=queue[j].nextExecutionTime)break;TimerTasktmp=queue[j];队列[j]=队列[k];队列[k]=tmp;k=j;文章。java.util.concurrent.ScheduledThreadPoolExecutor虽然Timer很好用,而且是线程安全的,但是对于Timer来说,如果要提交一个任务,需要创建一个TimerTask类来封装具体的任务,不是很通用。所以JDK在5.0引入了更通用的ScheduledThreadPoolExecutor,它是一个线程池,使用多个线程来执行特定的任务。当线程池的线程数等于1时,ScheduledThreadPoolExecutor相当于Timer。ScheduledThreadPoolExecutor中保存的任务是一个DelayedWorkQueue。DelayedWorkQueue与DelayQueue和PriorityQueue一样,都是基于堆的数据结构。因为堆需要不断的进行siftUp和siftDown重平衡操作,所以它的时间复杂度是O(logn)。下面是DelayedWorkQueue的shiftUp和siftDown的实际代码:privatevoidsiftUp(intk,RunnableScheduledFuture>key){while(k>0){intparent=(k-1)>>>1;RunnableScheduledFuture>e=queue[parent];如果(key.compareTo(e)>=0)中断;队列[k]=e;设置索引(e,k);k=父母;}队列[k]=键;设置索引(键,k);}privatevoidsiftDown(intk,RunnableScheduledFuture>key){inthalf=size>>>1;while(k
