android threadpool 类型,Android 线程池(ThreadPool)

0.jpeg

Android 线程池

简介什么是线程池线程池是一种线程使用模式。线程过多会带来调度开销,进而影响缓存局部性和整体性能。而线程池维护着多个线程,等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用,还能防止过分调度。

Android中的线程池的概念来源于Java中的Executor,Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor,ThreadPoolExecutor提供了一系列参数来配置线程池,通过不同的参数可以创建不同的线程池。

优点:1. 重用线程池中的线程,避免因为线程的创建和销毁带来的性能开销。

2. 能有效的控制线程池中的线程并发数,避免大量线程之间因为互相抢占资源而导致的阻塞现象。

3. 能够对线程进行简单的管理,并提供定时执行以及指定间隔循环执行等功能。

构造方法public ThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue workQueue, ThreadFactory threadFactory )CorePoolSize

线程的核心线程数。默认情况下,核心线程数会在线程中一直存活,即使它们处于闲置状态。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么核心线程就会存在超时策略,这个时间间隔由keepAliveTime所决定,当等待时间超过keepAliveTime所指定的时长后,核心线程就会被停止。

maximumPoolSize

线程池所能容纳的最大线程数。当活动线程数达到这个数值后,后续的新任务将会被阻塞。

keepAliveTime

非核心线程闲置时的超时时长,超过这个时长,非核心线程就会被回收,当ThreadPoolExector的allowCoreThreadTimeOut属性设置为True时,keepAliveTime同样会作用于核心线程。

unit

用于指定keepAliveTime参数的时间单位,这是一个枚举,常用的有:TimeUnit.NANOSECONDS 纳秒TimeUnit.MICROSECONDS 微秒TimeUnit.MILLISECONDS 毫秒TimeUnit.SECONDS 秒TimeUnit.MINUTES 分钟TimeUnit.HOURS 小时TimeUnit.DAYS 天

workQueue

线程池中的任务队列,通过线程池execute方法提交的Runnable对象会存储在这个参数中。这个任务队列是 BlockQueue 类型,属于阻塞队列,就是当队列为空的时候,此时取出任务的操作会被阻塞,等待任务加入队列中不为空的时候,才能进行取出操作,而在满队列的时候,添加操作同样被阻塞。

threadFactory

线程工厂,为线程池提供创建新线程的功能。ThreadFactory是一个接口,它只有一个方法,newThread(Runnable r),用来创建线程。ThreadFactory factory = new ThreadFactory() { //线程安全的Integer操作类 private final AtomicInteger mCount =new AtomicInteger(1); @Override public Thread newThread(Runnable r) { return new Thread(r, "new Thread #" + mCount.getAndIncrement()); }};

重要(常用)方法execute(),执行一个任务,没有返回值。

submit(),提交一个线程任务,有返回值。submit(Callable task) 能获取到它的返回值,通过future.get()获取( 阻塞直到任务执行完 )。一般使用FutureTask+Callable配合使用( IntentService中有体现 )。submit(Runnable task, T result)能通过传入的载体result间接获得线程的返回值。submit(Runnable task)则是没有返回值的,就算获取它的返回值也是null。

reject() 是线程创建失败的一个回调。

addWorker() 是创建线程(核心线程,非核心线程)的主要方法1. 增加一个线程,并且会为其绑定core或者maximum的线程标志.2. 如果成功添加线程来执行当前任务,那么当前线程池的状态会被刷新.3. 在添加第一个任务firstTask的这种情况下,新的工作线程会被创建后立即执行任务.4. 该方法会在线程池STOP状态或者符合资格去关闭会返回false.5. 线程工厂创建线程失败的时候,同样也会返回false.6. 在由于线程创建失败,线程工厂返回的线程为null,或者发生异常(通常由于在线程执行的过程中发生了OOM),线程池会进行回滚操作.

其他方法

addWorkedFailed()在addWorker()方法中,如果线程创建之后,没有最终运行(workerStarted=false)这时候会调用addWorkedFailed()方法.

tryTerminate()线程池创建线程失败,一般由于异常引起(或OOM),这时候需要让线程池进行停止操作.

shutdown()

中断所有空闲的线程方法,它的核心方法是调用interruptIdleWorkers()方法.在shutdown()执行时可以让现有的任务被执行,但是新的任务不在会被处理.

如果已经是SHUTDOWN状态,那么继续调用不会产生任何效果.

shutdown()方法只会中断空闲的线程,但是不会影响到已经存入队列的任务,如果需要停止线程池的运行,可以使用awaitTermination()方法.

interruptIdleWorkers()

这个方法作用很明确,是设置线程中断操作的方法,参数onlyOne作用如下 :如果为 true ,只中断工作线程中的一个线程.如果为 false ,中断所有的工作线程.

awaitTermination()

阻塞方法,强行等待当前队列中的任务全部为TERMINATED状态,可以设置超时时间.timeout —- 设置超时时间unit —- 设置超时时间的单位

常见的线程池及其用法定长线程池(FixedThreadPool)// 1. 创建定长线程池对象 & 设置线程池线程数量固定为3ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); }};// 3. 向线程池提交任务:execute()fixedThreadPool.execute(task);// 4. 关闭线程池fixedThreadPool.shutdown();特点:只有核心线程 & 不会被回收、线程数量固定、任务队列无大小限制(超出的线程任务会在队列中等待)

应用场景:控制线程最大并发数

具体使用:通过 Executors.newFixedThreadPool() 创建

定时线程池(ScheduledThreadPool )// 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:schedule()scheduledThreadPool.schedule(task, 1, TimeUnit.SECONDS); // 延迟1s后执行任务scheduledThreadPool.scheduleAtFixedRate(task,10,1000,TimeUnit.MILLISECONDS);// 延迟10ms后、每隔1000ms执行任务// 4. 关闭线程池scheduledThreadPool.shutdown();特点:核心线程数量固定、非核心线程数量无限制(闲置时马上回收)

应用场景:执行定时 / 周期性 任务

使用:通过Executors.newScheduledThreadPool()创建

可缓存线程池(CachedThreadPool)// 1. 创建可缓存线程池对象ExecutorService cachedThreadPool = Executors.newCachedThreadPool();// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:execute()cachedThreadPool.execute(task);// 4. 关闭线程池cachedThreadPool.shutdown();//当执行第二个任务时第一个任务已经完成//那么会复用执行第一个任务的线程,而不用每次新建线程。特点:只有非核心线程、线程数量不固定(可无限大)、灵活回收空闲线程(具备超时机制,全部回收时几乎不占系统资源)、新建线程(无线程可用时)任何线程任务到来都会立刻执行,不需要等待。

应用场景:执行大量、耗时少的线程任务

使用:通过Executors.newCachedThreadPool()创建

单线程化线程池(SingleThreadExecutor)// 1. 创建单线程化线程池ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();// 2. 创建好Runnable类线程对象 & 需执行的任务Runnable task =new Runnable(){ public void run(){ System.out.println("执行任务啦"); } };// 3. 向线程池提交任务:execute()singleThreadExecutor.execute(task);// 4. 关闭线程池singleThreadExecutor.shutdown();特点:只有一个核心线程(保证所有任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题)

应用场景:不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等

使用:通过Executors.newSingleThreadExecutor()创建

常见线程池的 总结 & 对比

762db94d9a72e849e756c1ff849f8f63.png

~~知人 · 有赞~~

0d292184d186807ad7c9bf601a0057c7.gif

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值