题目
给定一个包含非负整数的 _m_ x _n_
网格 grid
,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。
说明:每次只能向下或者向右移动一步。
执行线程需要一直运行,等待任务时间到了再执行。
所以需要一个死循环,让线程一直运行下去。
但是没有任务时,死循环会空转CPU,所以需要释放CPU。
如何让线程释放CPU,又让线程不死进行等待?
sleep()或wait(),把CPU交出去。
线程应该等待多久?
sleep()或wait()都可以传递要等待多长时间,等待时长可以用任务时间减去当前时间计算而来。
任务执行完后,计算新的等待时间,继续让线程等待。
每个任务都要有一个执行时间,按任务执行时间从小到大排序,先执行时间小的任务。
怎么排序?
观察任务添加的特点。
任务可能会动态添加,比如Android中的Handler,消息队列可以随时插入新的消息,并且消息的执行时间完全任意。
这就需要在线排序算法,用优先队列,创建最小堆,往堆中添加一个元素,调整堆只需要O(log n)的时间复杂度。
如果使用离线的基于比较的排序算法,时间复杂度O(n * log n),插入排序时间最短,最多花费O(n),但是都没调整堆时间少。
读取时间最小的任务,把它的执行时间减去当前时间,得到等待时间,让线程sleep或wait这个时间。
等到线程唤醒后,执行任务,从队列中移除这个已执行的任务,取下一个任务,再计算等待时间。
后续任务重复这个流程。
新任务添加到优先队列后,立刻唤醒执行线程,重新计算要等待的时间,保证执行线程始终等待执行时间最小的时间的任务。
开启多个执行线程,多线程从同一个任务队列中取任务,队列中的任务按时间排序好。
相当于设计一个带延迟功能的线程池了,即ScheduledThreadPoolExecutor。
1 | private const val STATE_A = 1 |
1 | import java.util.concurrent.locks.ReentrantLock |
1 | import java.util.concurrent.Semaphore |
1 | import java.util.concurrent.CountDownLatch |
1 | import java.util.concurrent.CyclicBarrier |
1 | private const val STATE_A = 1 |
看官方介绍
AMS
和IContentProvider
,hook过程做了充分的兼容性适配;让应用能够在无需重新安装的情况实现更新,帮助应用快速建立动态修复能力。
热修复是一个动态修改代码与资源的方式,适合于修改量较少的情况。
传统的APP发布升级流程慢,热补丁可以在更短的时间内发布,非常适合在灰度阶段快速验证问题是否已修复,大大缩短发布流程。
热补丁技术可以降低开发成本,缩短开发周期,实现轻量而快速的升级。
排查用户反馈的问题会遇到”本地不复现”,”日志查不出”,”联系用户不鸟你”等情况,只要能向特定用户发送补丁,就可以很方便的排查问题,不用依赖用户操作,可以默默的就排查解决。
可以方便的进行ABTest,对不同的用户群发送不同的补丁,做不同的行为统计