ThreadPool&AsyncTask

来源:互联网 发布:软件开发工程师怎么样 编辑:程序博客网 时间:2024/06/05 12:39

ThreadPool&AsyncTask

ThreadPool线程池

  • new Thread的弊端如下:
    a. 每次new Thread新建对象性能差。
    b. 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。
    c. 缺乏更多功能,如定时执行、定期执行、线程中断。
  • 相比new Thread,Java提供的四种线程池的好处在于:
    a. 重用存在的线程,减少对象创建、消亡的开销,性能佳。
    b. 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
    c. 提供定时执行、定期执行、单线程、并发数控制等功能。
  • 线程池的创建:
    1、new ThreadPoolExecutor的方式
    ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, workQuene, threadFactory, handler);//              corePoolSize 核心线程数//              maximumPoolSize 最大线程数//              keepAliveTime 超过核心线程数后创建的线程存活时间//              unit 时间单位//              workQuene 工作队列//              threadFactory 默认线程对象//              handler 异常处理对象

**形象解释:**ThreadPoolExecutor中额定的“工人”数量由corePoolSize决定,当任务数量超过额定工人数量时,将任务缓存在BlockingQueue之中,当发现如果连queue中也放不下时(可能是因为使用有界queue,也可能是使用SynchronousQueue),ThreadPoolExecutor会请求“老板”再派几个“工人”过来。

假设后来向老板派来的工人始终是“借来的”,俗话说“有借就有还”,但这里的问题就是什么时候还了,如果借来的工人刚完成一个任务就还回去,后来发现任务还有,那岂不是又要去借?这一来一往,老板肯定头也大死了。

合理的策略:既然借了,那就多借一会儿。直到“某一段”时间后,发现再也用不到这些工人时,便可以还回去了。这里的某一段时间便是keepAliveTime的含义,TimeUnit为keepAliveTime值的度量。

2、通过Executors提供的四种线程池

  • newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
    示例代码如下:
//线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。ExecutorService cachedThreadPool = Executors.newCachedThreadPool();for (int i = 0; i < 10; i++) {    final int index = i;    try {        Thread.sleep(index * 1000);    } catch (InterruptedException e) {        e.printStackTrace();    }    cachedThreadPool.execute(new Runnable() {        @Override        public void run() {            System.out.println(index);        }    });}

  • newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
//因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。//定长线程池的大小最好根据系统资源进行设置。如//Runtime.getRuntime().availableProcessors()。可参考PreloadDataCache。ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);for (int i = 0; i < 10; i++) {    final int index = i;    fixedThreadPool.execute(new Runnable() {        @Override        public void run() {            try {                System.out.println(index);                Thread.sleep(2000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    });}

  • newScheduledThreadPool创建一个定长线程池,支持定时及周期性任务执行。
//表示延迟3秒执行。ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);scheduledThreadPool.schedule(new Runnable() {    @Override    public void run() {        System.out.println("delay 3 seconds");    }}, 3, TimeUnit.SECONDS);//定期执行示例 表示延迟1秒后每3秒执行一次。//ScheduledExecutorService比Timer更安全,功能更强大,后面会有一篇单独进行对比。scheduledThreadPool.scheduleAtFixedRate(new Runnable() {    @Override    public void run() {        System.out.println("delay 1 seconds, and excute every 3 seconds");    }}, 1, 3, TimeUnit.SECONDS);

  • newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
//结果依次输出,相当于顺序执行各个任务。//现行大多数GUI程序都是单线程的。Android中单线程可用于数据库操作,文件操作,应用批量安装,应用批量删除等不适合并发但可能IO阻塞性及影响UI线程响应的操作。ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();for (int i = 0; i < 10; i++) {    final int index = i;    singleThreadExecutor.execute(new Runnable() {        @Override        public void run() {            try {                System.out.println(index);                Thread.sleep(2000);            } catch (InterruptedException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    });}

自封装ThreadManager举例:

import java.util.concurrent.Executors;import java.util.concurrent.LinkedBlockingQueue;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;public class ThreadManager {    private static Object obj = new Object();    private static ThreadPoolProxy threadPoolProxy;    public static ThreadPoolProxy getThreadPoolProxy() {        synchronized (obj) {            if (threadPoolProxy == null) {                threadPoolProxy = new ThreadPoolProxy(1, 2, 100);            }            return threadPoolProxy;        }    }    public static class ThreadPoolProxy {        private int corePoolSize;        private int maximumPoolSize;        private long keepAliveTime;        public ThreadPoolProxy(int corePoolSize, int maximumPoolSize, long keepAliveTime) {            this.corePoolSize = corePoolSize;            this.maximumPoolSize = maximumPoolSize;            this.keepAliveTime = keepAliveTime;        }        public void excute(Runnable runnable) {            if (runnable != null) {                ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,                        keepAliveTime, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(),                        Executors.defaultThreadFactory(), new AbortPolicy());                threadPoolExecutor.execute(runnable);            }        }        public static void main(String[] args) {            ThreadManager.getThreadPoolProxy().excute(new Runnable() {                public void run() {                    while (true) {                        System.out.println("----------");                    }                }            });        }    }}

AsyncTask<Params,Progress,Result>
step1:继承AsyncTask

       Params:输入参数。对应的是调用自定义的AsyncTask的类中调用excute()方法中传递的参数。如果不需要传递参数,则直接设为Void即可。       Progress:子线程执行的百分比       Result:返回值类型。和doInBackground()方法的返回值类型保持一致。

step2:实现以下几个方法:执行时机和作用看示例代码,以下对返回值类型和参数进行说明

      onPreExecute():无返回值类型。不传参数      doInBackground(Params... params):返回值类型和Result保持一致。参数:若无就传递Void;若有,就可用Params      publishProgress(Params... params):在执行此方法的时候会直接调用onProgressUpdate(Params... values)      onProgressUpdate(Params... values):无返回值类型。参数:若无就传递Void;若有,就可用Progress      onPostExecute(Result  result) :无返回值类型。参数:和Result保持一致。

step3:在调用自定义的AsyncTask类中生成对象;

      执行  :对象.excute(Params... params);

注意:

   1) Task的实例必须在UI thread中创建   2) execute方法必须在UI thread中调用   3) 不要手动的调用onPreExecute、onPostExecute doInBackground、 onProgressUpdate这几个方法   4) 该task只能被执行一次,否则多次调用时将会出现异常

AsyncTask本质还是调用的ThreadPool,分同步SERIAL_EXECUTOR和异步THREAD_POOL_EXECUTOR两种方式
asynct.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, 0);
asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0);

AsyncTask只是封装了线程池、封装了UIThread与子Thread的通讯

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 两岁宝宝小蛋蛋肿了怎么办 吃大胺片过敏蛋皮又痛又痒怎么办 刚出生二十天宝宝蛋蛋有疝气怎么办 宝宝八个月蛋蛋一个没掉下来怎么办 引产23天同房内射肚子疼怎么办l 房东禁止养宠物如果养了怎么办 圆通快递退回但没有签收记录怎么办 信用卡没有收到又退回去了怎么办 新疆不给邮寄快递被退回运费怎么办 淘宝上已付款还在想留言怎么办 b超显示肾结石但x光看不到怎么办 洗脚让洗脚妹摸射精了怎么办 在新疆塔城干活不给工资怎么办 挨打了屁股肿的又大又硬怎么办 李贞将军有关电影小腿肌腱疼怎么办 朋友老婆老是背地里说我坏话怎么办 当你听到别人在背后说你时怎么办 分手了和前任是同事需要见面怎么办 和附近的人聊天他约你见面怎么办 微信约妹子发完红包拉黑了怎么办 户口本被前妻扣着不能结婚怎么办 部队当兵户口没注销退伍回去怎么办 没打疫苗的狗狗咬了我的嘴巴怎么办 新车被撞了还没上牌怎么办? 签了合同上两天班想辞职怎么办 刚到公司上班两天想辞职怎么办 签入职合同一天后就不想干了怎么办 入职材料交了第二天就想离职怎么办 宝宝40周多了还不想出来怎么办 工厂上班不到三个月不给辞工怎么办 单位辞职后不上班了保险怎么办 药流6个小时没流下来怎么办 小孩有口臭怎么办这几天不想吃饭 七个月宝宝口臭不想吃饭怎么办啊 老公工作累想要辞职不上班怎么办 药物流产后第6天咋下坠的怎么办 药流第一天胎囊没有掉下来怎么办 药流还有一点没流干净怎么办 3个月的宝宝被电了一下怎么办 宝宝吃奶粉过敏下巴红有疙瘩怎么办 小孩牙齿没掉又长出新牙怎么办