之前由于工作比较忙就随便写了一下线程池方面的面试回答,非常简陋,今天回首看了看是如此的不堪入目,于是乎激发了我重新整理一遍的决心.
关于线程的使用,做开发的不会还有人不知道怎么使用吧? 呐,入下图所示就是最简单的线程使用
是不是觉得很简单
这得从google 创造Thread 对象的时候说起.
话说从前google创建Thread的时候无论是创建Thread对象还是销毁Thread对象都会消耗cpu资源,而且线程的运行是抢占式的,某个时间段那个线程抢到执行权就会先执行事件线程一多就会出现相互抢占的情况,而且同一时刻也会出现多个线程抢着关闭的情况.这里只是说会存在这种情况不是一定会出现这种情况(语文不好的同学不要钻牛角尖),那出现这种情况是不是就会抢占cpu资源,嘿嘿
书接上回 也就是上边
既然存在这种情况,那google爸爸可就不能不管了,于是乎google 就提供了Executors 类提供四个现成的线程池他们分别是
SingleThreadPool 核心线程和非核心线程都是1 无超时限制不会被回收
CacheThreadPool 无核心线程.非核心线程数Integer最大值 有存活时间限制,超时直接回收
FixedThreadPool 核心线程和非核心线程一至 空闲不会被回收
ScheduleThreadPool 核心线程大小有限制.非核心线程Integer最大值 空闲直接回收
好了现在轮到线程池大佬出场了,主要你有点进去看过这四个线程池里边的实现源码你就会发现,其实他们都是通过 ThreadPoolExecutor 进行创建的,
对,没错,自定义线程池就得用到ThreadPoolExecutor
ThreadPoolExecutor的几个参数
corePoolSize 核心线程大小
maximunPoolSize 非核心线程大小
keepAliveTime 保留时间
TimeUnit 时间单位
BlockingQueue 事件队列
ThreadFactory 线程工厂
RejectedExecuttionHandler 任务队列已满回调策略
现在大概明白线程池是个什么东东了吧
定义IO/CPU密集型线程池 就需要根据CPU的进程数进行参数配置
将 corePoolSize 和 maximumPoolSize都设置成 CPU进程数 * 2 + 1 即可
CPU进程数获取
Runtime.getRumtime().availableProcessors()
em....... 就说到这里了,更加详细的ThreadPool自定义可以看看下边这个大佬写的,可以说是相当详细了
package com.nova.lib.util
import android.os.Build
import androidx.annotation.RequiresApi
import com.nova.base.util.log.LogUtil
import java.util.concurrent.LinkedBlockingDeque
import java.util.concurrent.RejectedExecutionHandler
import java.util.concurrent.ThreadFactory
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import java.util.concurrent.atomic.AtomicInteger
@RequiresApi(Build.VERSION_CODES.N)
object ThreadPoolUtil {
private val TAG = "ThreadPoolUtil"
private val CPU_COUNT = Runtime.getRuntime().availableProcessors()
private val corePoolSize = CPU_COUNT * 2 + 1
private val maximumPoolSize = CPU_COUNT * 2 + 1
// private val keepAliveUnit =
private val keepAliveTime = 60L
lateinit var threadPoolExecutor: ThreadPoolExecutor
fun execute() {
if (!this::threadPoolExecutor.isInitialized) {
threadPoolExecutor = ThreadPoolExecutor(
corePoolSize,
maximumPoolSize,
keepAliveTime,
TimeUnit.SECONDS,
LinkedBlockingDeque(),
MyThreadFactory()
) { runnable, threadPoolExecutor ->
if (!threadPoolExecutor.isShutdown) {
// 尝试移除队列头部任务,然后再重新添加到队列
threadPoolExecutor.queue.poll()
threadPoolExecutor.execute(runnable)
}
LogUtil.d(TAG, "线程池异常收集 ")
}
}
// 线程池定义的四种拒绝策略
// ThreadPoolExecutor.AbortPolicy 抛出异常
// ThreadPoolExecutor.CallerRunsPolicy 循环重试
// ThreadPoolExecutor.DiscardPolicy 丢弃无法执行的任务
// ThreadPoolExecutor.DiscardOldestPolicy 移除队列头部任务,并执行当前任务
}
class MyThreadFactory : ThreadFactory {
var atomicInteger = AtomicInteger()
val name = "-io-"
override fun newThread(p0: Runnable?): Thread {
return Thread(p0, "${ContextUtil.topAct}$name${atomicInteger.getAndIncrement()}")
}
}
}
一位靓仔博主总结得不错哦
Java并发编程:线程池的使用 - Matrix海子 - 博客园
关于线程池(并发)使用会遇到的问题