android 运用线程池实现异步队列的方法

165 阅读1分钟

实现工具类

package com.lujianfei.composeui.utils


/**
 * Author: lujianfei
 * Date: 2024/5/27 11:57
 * Description:
 */

import android.util.Log
import java.util.ArrayDeque
import java.util.concurrent.ArrayBlockingQueue
import java.util.concurrent.BlockingQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit

class ThreadPool private constructor() {

    companion object {
        /**
         * 系统最大可用线程
         */
        private val CPU_AVAILABLE = Runtime.getRuntime().availableProcessors()

        /**
         * 最大线程数
         */
        private val MAX_POOL_COUNTS = CPU_AVAILABLE * 2 + 1

        /**
         * 线程存活时间
         */
        private const val AVAILABLE = 1L

        /**
         * 核心线程数
         */
        private val CORE_POOL_SIZE = CPU_AVAILABLE + 1

        val instance by lazy { ThreadPool() }
    }

    private var mActive: Runnable? = null

    /**
     * java线程池
     */
    private var threadPoolExecutor: ThreadPoolExecutor?

    /**
     * 线程池缓存队列
     */
    private val mWorkQueue: BlockingQueue<Runnable> = ArrayBlockingQueue(CORE_POOL_SIZE)
    private val mArrayDeque = ArrayDeque<Runnable>()

    init {
        threadPoolExecutor = ThreadPoolExecutor(
            CORE_POOL_SIZE,
            MAX_POOL_COUNTS,
            AVAILABLE,
            TimeUnit.SECONDS,
            mWorkQueue
        )
    }

    /**
     * 并行线程
     */
    fun addParallelTask(runnable: Runnable?) {
        if (runnable == null) {
            throw NullPointerException("addParallelTask(Runnable runnable)传入参数为空")
        }
        threadPoolExecutor?.let { threadPoolExecutor->
            if (threadPoolExecutor.activeCount < MAX_POOL_COUNTS) {
                Log.i(
                    "Lee",
                    "目前有" + threadPoolExecutor.activeCount + "个线程正在进行中,有" + mWorkQueue.size + "个任务正在排队"
                )
                synchronized(this) { threadPoolExecutor.execute(runnable) }
            }
        }
    }

    /**
     * 串行线程
     */
    @Synchronized
    fun addSerialTask(r: Runnable?) {
        if (r == null) {
            throw NullPointerException("addTask(Runnable runnable)传入参数为空")
        }
        mArrayDeque.offer(Runnable {
            try {
                r.run()
            } finally {
                scheduleNext()
            }
        })
        // 第一次入队列时mActivie为空,因此需要手动调用scheduleNext方法
        if (mActive == null) {
            scheduleNext()
        }
    }

    private fun scheduleNext() {
        if (mArrayDeque.poll().also { mActive = it } != null) {
            threadPoolExecutor?.execute(mActive)
        }
    }

    fun stopThreadPool() {
        threadPoolExecutor?.shutdown()
        threadPoolExecutor = null
    }
}

使用方法

ThreadPool.instance.addSerialTask {
    // 需要执行的串行耗时任务
}

效果展示

这里为了 UI 实现方便,使用 Compose 编写示例

@Composable
private fun example1() {
    val actions = remember {
        mutableStateListOf<ThreadAction>()
    }
  Column {
      Button(modifier = Modifier.padding(start = 15.dp), onClick = {
          val currentAction = ThreadAction(label = "任务${actions.size + 1}").apply { status.value = ThreadStatus.Running }
          actions.add(0, currentAction)
          ThreadPool.instance.addSerialTask {
              Thread.sleep(1000)
              currentAction.status.value = ThreadStatus.Finished
          }
      }) {
          Text(text = "新增任务")
      }
      LazyColumn {
        items(actions) {
            Text(text = "${it.label} ${it.status.value.label}", Modifier.padding(start = 15.dp, top = 5.dp))
        }
      }
  }
}

data class ThreadAction(val label:String) {
    val status = mutableStateOf(ThreadStatus.Running)
}

enum class ThreadStatus(val label:String) {
    Running("正在执行"),
    Finished("已完成")
}