几个注意点
-
ReentrantLock 和 Condition 用于唤醒和线程休眠
-
通过 ThreadFactory 来创键线程,重写 beforeExecute,afterExecute 来处理逻辑
-
kotlin 通过 @Synchronized 注解,来简便的使用锁
需要解决
- 怎样实现按优先级来执行?
- 怎样让任务执行的结果,最终回调到主线程?
怎样实现按优先级来执行?
通过 PriorityBlockingQueue + 一个实现 Comparable 接口的 Runnable 来实现
由于 PriorityBlockingQueue 是一个按优先级顺序排列的阻塞队列,它在使用上需要我们实现对比优先级的代码
我们通过实现 Comparable 的 compareTo() : Int, 这里通过返回的 Int 值决定优先级:
-
如果两个元素的 compareTo() 方法返回 0,则两个元素具有相同的优先级
-
如果两个元素的 compareTo() 方法返回负数,则第一个元素的优先级高于第二个元素。
-
如果两个元素的 compareTo() 方法返回正数,则第一个元素的优先级低于第二个元素。
怎样让任务执行的结果,最终回调到主线程?
在我看来,可以拆分成两个小问题:
-
返回执行的结果
-
将结果回调到主线程中(使用 Handler.post 到主线程中执行)
实现代码
/**
* 优先级比较的 Runnable
*/
class PriorityRunnable(val priority : Int, val runnable: Runnable) : Runnable,Comparable<PriorityRunnable>{
override fun run() {
runnable.run()
}
override fun compareTo(other: PriorityRunnable): Int {
// 优先级的计算方式
//具体来说,PriorityBlockingQueue 会将元素按照以下规则进行排序:
//如果两个元素的 compareTo() 方法返回 0,则两个元素具有相同的优先级。
//如果两个元素的 compareTo() 方法返回负数,则第一个元素的优先级高于第二个元素。
//如果两个元素的 compareTo() 方法返回正数,则第一个元素的优先级低于第二个元素。
return if (priority > other.priority) 1 else if (priority < other.priority) -1 else 0
}
}
/**
* 线程池工具 (CPU 密集型),支持暂停/恢复
* 可用于批量上传下载
* 按优先级的顺序来执行
*
*/
object KExecutors {
private val TAG = "KExecutors"
private var mKExecutor: ThreadPoolExecutor
// 用来实现暂停和恢复执行
private val mLock = ReentrantLock()
private val mCondition = mLock.newCondition()
private var mPaused = false
// 执行结果发送到主线程中
private val mHandler = Handler(Looper.getMainLooper())
init {
val coreThreadSize = Runtime.getRuntime().availableProcessors() + 1
val maxThreadSize = coreThreadSize * 2 + 1
val keepAliveTime = 20L
val unit = TimeUnit.SECONDS
val queue = PriorityBlockingQueue<Runnable>()
val threadName = AtomicLong()
val threadFactory = ThreadFactory {
val thread = Thread(it)
thread.name = "KLib-Thread-" + threadName.getAndIncrement()
return@ThreadFactory thread
}
mKExecutor = object : ThreadPoolExecutor(
coreThreadSize,
maxThreadSize,
keepAliveTime,
unit,
queue,
threadFactory
) {
override fun beforeExecute(t: Thread?, r: Runnable?) {
// 判断是否已经暂停了,如果暂停就不要执行了
if (mPaused) {
mLock.lock()
try {
mCondition.await()
} finally {
mLock.unlock()
}
}
}
override fun afterExecute(r: Runnable?, t: Throwable?) {
// 打印当前工作线程数
r as PriorityRunnable
Log.e(TAG, "已经执行完成的线程的优先级为" + r.priority)
// 打印线程任务的执行时间
}
}
}
fun execute(@IntRange(from = 0, to = 10) priority: Int = 0, runnable: Runnable) {
mKExecutor.execute(PriorityRunnable(priority, runnable))
}
/**
* 将返回值 post 到主线程的方法
* <*> 表示可以为任意值
*/
fun executeCallable(@IntRange(from = 0, to = 10) priority: Int = 0, callable: Callable<*>) {
mKExecutor.execute(PriorityRunnable(priority, callable))
}
/**
* 这里调用 pause,已经加入的任务不会马上暂停,会在执行下一个任务前判断
* 具体见 beforeExecute() 中实现
*/
@Synchronized
fun pause() {
mPaused = true
Log.e(TAG, "pause")
}
/**
* 唤醒
* Synchronized 用于多线程调用加锁
* Condition 用于唤醒线程
*/
@Synchronized
fun resume() {
mPaused = false
mLock.lock()
try {
// 唤醒所有阻塞的线程
mCondition.signalAll()
} finally {
mLock.unlock()
}
Log.e(TAG, "resume")
}
@Synchronized
fun isPaused(): Boolean {
return mPaused
}
/**
* 执行代返回值的
*/
abstract class Callable<T> : Runnable {
abstract fun onBeforeRun()
abstract fun onBackground(): T
abstract fun onCompleted(t: T)
override fun run() {
mHandler.post {
onBeforeRun()
}
val t = onBackground()
mHandler.post {
onCompleted(t)
}
}
}
}