赞
踩
- new Thread(new Runnable() {
-
- @Override
- public void run() {
- 。。。。。。
- }
- }).start();
new Thread的弊端如下:
a. 每次new Thread新建对象性能差。
b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,线程过多,导致各个线程竞争抢夺CPU执行权,线程的频繁切换导致效率的降低,及可能占用过多系统资源导致死机或oom。
c. 缺乏更多功能,如定时执行、定期执行、线程中断。
1.重用线程池中的线程,避免频繁创建进而导致的频繁GC所带来的性能开销
2.能有效的控制线程最大并发数,合理使用系统资源,避免大量线程之间因相互抢占资源而导致的阻塞现象
3.可以有效的控制线程的执行,比如定时执行,取消执行等
Android中的线程池的概念来源于java中的Executor,Executor是一个接口,真正的线程池的实现为ThreadPoolExecutor
- public interface Executor {
- void execute(Runnable var1);
- }
- public interface ExecutorService extends Executor {}
- public abstract class AbstractExecutorService implements ExecutorService {}
-
- public class ThreadPoolExecutor extends AbstractExecutorService {
- ..........
- public void execute(Runnable command) {
- if (command == null) {
- throw new NullPointerException();
- } else {
- int c = this.ctl.get();
- if (workerCountOf(c) < this.corePoolSize) {
- if (this.addWorker(command, true)) {
- return;
- }
-
- c = this.ctl.get();
- }
-
- if (isRunning(c) && this.workQueue.offer(command)) {
- int recheck = this.ctl.get();
- if (!isRunning(recheck) && this.remove(command)) {
- this.reject(command);
- } else if (workerCountOf(recheck) == 0) {
- this.addWorker((Runnable)null, false);
- }
- } else if (!this.addWorker(command, false)) {
- this.reject(command);
- }
-
- }
- }
- .........
-
- }
下面介绍ThreadPoolExecutor的构造方法中各个参数的含义:
- // 一个比较常用的构造方法
- public ThreadPoolExecutor (int corePoolSize,
- int maximumPoolSize,
- long keepAliveTime,
- TimeUnit unit,
- BlockingQueue<Runnable workQueue>,
- ThreadFactory threadFactory )
corePoolSize:
线程池的核心线程数,默认情况下,核心线程会在线程池中一直存活,即使它们处于闲置状态。如果将ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true,那么闲置的核心线程在等待新任务到来时会有超时策略,这个时间间隔由keepAliveTime所指定,当等待时间超时超过keepAliveTime所指定的时长后,核心线程会被终止。
maxumumPoolSize:
线程池所能容纳的最大线程数,当活动线程达到这个数值后,后续的新任务将会被阻塞。
keepAliveTime:
非核心线程闲置时的超时时长,超过这个时长,非核心线程就会被回收。当ThreadPoolExecutor的allowCoreThreadTimeOut属性设置为true时,keepAliveTime同样会作用于核心线程。
unit:
用于指定keepAliveTime参数的时间单位,这是一个枚举,常用的有TimeUnit.MILLSECONDS(毫秒),TimeUnit.SECONDS(秒)以及TimeUnit.MINUTES(分钟)。
workQueue:
线程池中的任务队列,通过线程池的execute方法提交的Runnable对象会存储在这个参数中
threadFactory:
线程工厂,为线程池提供创建新线程的功能。ThreadFactory是一个接口,它只有一个方法:
Thread newThread(Runnable var1);
线程池的使用流程如下:
- // 1. 创建线程池
- // 创建时,通过配置线程池的参数,从而实现自己所需的线程池
- Executor threadPool = new ThreadPoolExecutor(
- CORE_POOL_SIZE,
- MAXIMUM_POOL_SIZE,
- KEEP_ALIVE,
- TimeUnit.SECONDS,
- sPoolWorkQueue,
- sThreadFactory
- );
- // 注:在Java中,已内置4种常见线程池,下面会详细说明
-
- // 2. 向线程池提交任务:execute()
- // 说明:传入 Runnable对象
- threadPool.execute(new Runnable() {
- @Override
- public void run() {
- ... // 线程执行任务
- }
- });
-
- // 3. 关闭线程池shutdown()
- threadPool.shutdown();
-
- // 关闭线程的原理
- // a. 遍历线程池中的所有工作线程
- // b. 逐个调用线程的interrupt()中断线程(注:无法响应中断的任务可能永远无法终止)
-
- // 也可调用shutdownNow()关闭线程:threadPool.shutdownNow()
- // 二者区别:
- // shutdown:设置 线程池的状态 为 SHUTDOWN,然后中断所有没有正在执行任务的线程
- // shutdownNow:设置 线程池的状态 为 STOP,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行任务的列表
- // 使用建议:一般调用shutdown()关闭线程池;若任务不一定要执行完,则调用shutdownNow()
根据参数的不同配置,Java
中最常见的线程池有4类:
FixedThreadPool
)ScheduledThreadPool
)CachedThreadPool
)SingleThreadExecutor
)即 对于上述4类线程池,
Java
已根据 应用场景 配置好核心参数
- // 1. 创建定长线程池对象 & 设置线程池线程数量固定为3
- ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
-
- // 2. 创建好Runnable类线程对象 & 需执行的任务
- Runnable task =new Runnable(){
- public void run(){
- System.out.println("执行任务啦");
- }
- };
-
- // 3. 向线程池提交任务:execute()
- fixedThreadPool.execute(task);
-
- // 4. 关闭线程池
- fixedThreadPool.shutdown();
举个例子:
- // 1. 创建定长线程池对象 & 设置线程池线程数量固定为4
- ExecutorService pool = Executors.newFixedThreadPool(4);
-
- Thread thread;
- //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
- for (int i = 0; i < 10; i++) {
- thread = new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "正在执行。。。");
- }
- });
- pool.execute(thread);//向线程池提交任务
- }
- pool.shutdown(); //关闭线程池
-
-
- //打印结果
- pool-1-thread-1正在执行。。。
- pool-1-thread-4正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-4正在执行。。。
- pool-1-thread-3正在执行。。。
- pool-1-thread-2正在执行。。。
- pool-1-thread-3正在执行。。。
- pool-1-thread-4正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-2正在执行。。。
- // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为5
- ScheduledExecutorService 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();
举个例子:
- // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为2
- ScheduledExecutorService pool= Executors.newScheduledThreadPool(2);
- Thread thread;
- long a=System.currentTimeMillis();
- //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
- for (int i = 0; i < 10; i++) {
- thread = new Thread(new Runnable() {
- @Override
- public void run() {
- long b=System.currentTimeMillis();
-
- System.out.println(Thread.currentThread().getName() +"延迟"+ (b-a)/1000+"S执行");
- }
- });
- pool.schedule(thread,3,TimeUnit.SECONDS);//向线程池提交任务
-
- }
- pool.shutdown(); //关闭线程池
- 输出结果//
- pool-1-thread-2延迟3S执行
- pool-1-thread-1延迟3S执行
- pool-1-thread-1延迟3S执行
- pool-1-thread-2延迟3S执行
- pool-1-thread-1延迟3S执行
- pool-1-thread-2延迟3S执行
- pool-1-thread-1延迟3S执行
- pool-1-thread-2延迟3S执行
- pool-1-thread-1延迟3S执行
- pool-1-thread-2延迟3S执行
定期执行:
- // 1. 创建 定时线程池对象 & 设置线程池线程数量固定为1
- ScheduledExecutorService pool= Executors.newScheduledThreadPool(1);
- //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
-
- pool.scheduleAtFixedRate(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() );
-
- }
- }, 1, 3, TimeUnit.SECONDS);//表示延迟1秒后每3秒执行一次。
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();
-
- //当执行第二个任务时第一个任务已经完成
- //那么会复用执行第一个任务的线程,而不用每次新建线程。
特点:只有一个核心线程(确保所有任务按照指定顺序在同一个线程中执行,不需要处理线程同步的问题)
应用场景:不适合并发但可能引起IO阻塞性及影响UI线程响应的操作,如数据库操作,文件操作等
使用:通过Executors.newSingleThreadExecutor()创建
示例:
- // 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();
-
举个例子:
- ExecutorService pool = Executors.newSingleThreadExecutor();
- Thread thread;
- //创建实现了Runnable接口对象,Thread对象当然也实现了Runnable接口
- for (int i = 0; i < 10; i++) {
- thread = new Thread(new Runnable() {
- @Override
- public void run() {
- System.out.println(Thread.currentThread().getName() + "正在执行。。。");
- }
- });
- pool.execute(thread);//向线程池提交任务
- }
- pool.shutdown(); //关闭线程池
-
- //输出日志//
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
- pool-1-thread-1正在执行。。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。