Android之AsyncTask线程池

asynctask 相比于 handler 在启动线程不多,代码要求简洁的情况下,使用起来相当方便

1.定义

public abstract class AsyncTask<Params, Progress, Result> 

有三个参量,分别为输入参量,中间反馈参量,结果返回参量

2.继承及实例化

 

    class myAsyncTask extends AsyncTask<String, Void, String> {

        TextView mytv;
        String tvname;
        //构造函数,根据需要重写
        myAsyncTask(TextView tv,String tvname) {
            this.mytv = tv;
            this.tvname=tvname;
        }
        
        //耗时任务,唯一一个不运行在主线程的函数
        @Override
        protected String doInBackground(String... params) {
            try {
                Thread.sleep(30000);//模拟下载,休眠
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return tvname;
        }

        //返回结果处理,更新UI等操作
        @Override
        protected void onPostExecute(String result) {
            // TODO Auto-generated method stub
            super.onPostExecute(result);
            mytv.setText(result);
        }

    }

 

3.主Activity,定义两个TextView用于显示结果

public class MainActivity extends Activity {

    private TextView tv1;
    private TextView tv2;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = (TextView) this.findViewById(R.id.tv1);
        tv2 = (TextView) this.findViewById(R.id.tv2);
        myAsyncTask mtask1=new myAsyncTask(tv1, "textview1");
        myAsyncTask mtask2=new myAsyncTask(tv2, "textview2");
        mtask1.execute();
        mtask2.execute();
        
//        mtask1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
//        
//        mtask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        
    }

看结果:刚启动只有一个asynctask运行,进入doinbackground函数休眠

线程1执行完毕,线程2启动,进入doinbackground函数休眠

两个线程均执行完毕

a.我们可以看到,两个线程是顺序进行的,有点串行的味道,来看看execute函数干了些什么

 public final AsyncTask<Params, Progress, Result> execute(Params... params) {
        return executeOnExecutor(sDefaultExecutor, params);
    }
private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
 public static final Executor SERIAL_EXECUTOR = new SerialExecutor();
private static class SerialExecutor implements Executor {
        final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>();
        Runnable mActive;

        public synchronized void execute(final Runnable r) {
            mTasks.offer(new Runnable() {
                public void run() {
                    try {
                        r.run();
                    } finally {
                        scheduleNext();
                    }
                }
            });
            if (mActive == null) {
                scheduleNext();
            }
        }

        protected synchronized void scheduleNext() {
            if ((mActive = mTasks.poll()) != null) {
                THREAD_POOL_EXECUTOR.execute(mActive);//这个被实例化的接口,稍后还会看到
            }
        }
    }

我们看见了ArrayDeque,也就明白了,为什么线程会一个一个的顺序执行了

b.我们来试试另一种启动线程的方式:

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = (TextView) this.findViewById(R.id.tv1);
        tv2 = (TextView) this.findViewById(R.id.tv2);
        myAsyncTask mtask1=new myAsyncTask(tv1, "textview1");
        myAsyncTask mtask2=new myAsyncTask(tv2, "textview2");
//        mtask1.execute();
//        mtask2.execute();
        
        mtask1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        
        mtask2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
        
    }

看运行结果:可以看到,两个线程同时运行起来了

休眠过后,两个线程均停止

看看源码:

 public final AsyncTask<Params, Progress, Result> executeOnExecutor(Executor exec,
            Params... params) {
        if (mStatus != Status.PENDING) {
            switch (mStatus) {
                case RUNNING:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task is already running.");
                case FINISHED:
                    throw new IllegalStateException("Cannot execute task:"
                            + " the task has already been executed "
                            + "(a task can be executed only once)");
            }
        }

        mStatus = Status.RUNNING;

        onPreExecute();

        mWorker.mParams = params;
        exec.execute(mFuture);

        return this;
    }

我们传入的执行器:AsyncTask.THREAD_POOL_EXECUTOR

 public static final Executor THREAD_POOL_EXECUTOR
            = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                    TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory);

我们可以看到最终回到了a节结尾处提到的 THREAD_POOL_EXECUTOR 接口对象,只不过a节中把队列中的线程一个一个取出来执行,而b节中的线程则是并发执行

看看THREAD_POOL_EXECUTOR 定义:

 public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             threadFactory, defaultHandler);
    }
    private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors();
    private static final int CORE_POOL_SIZE = CPU_COUNT + 1;
    private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1;
    private static final int KEEP_ALIVE = 1;

构造器的参数说明如下(下文参考:http://blog.sina.com.cn/s/blog_8417aea80100t483.html

A.    corePoolSize: 线程池维护线程的最少数量
B.    maximumPoolSize:线程池维护线程的最大数量
C.    keepAliveTime: 线程池维护线程所允许的空闲时间
D.    unit: 线程池维护线程所允许的空闲时间的单位
E.    workQueue: 线程池所使用的缓冲队列
F.    handler: 线程池对拒绝任务的处理策略当一个任务通过asynct.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, 0)方法欲添加到线程池时:

如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。
如果此时线程池中的数量等于 corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。
如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。
也就是:处理任务的优先级为:
核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。
当线程池中的线程数量大于 corePoolSize时,如果某线程空闲时间超过keepAliveTime,线程将被终止。这样,线程池可以动态的调整池中的线程数。

总结:

当我们需要更新的UI控件相互不存在干扰的情况下完全可以调用 executeOnExecutor,异步任务可以加入AsyncTask自定义的线程池(AsyncTask.THREAD_POOL_EXECUTOR)执行

当然这个线程池管理器我们也可以自己定义,例如:

 

        ExecutorService pool = Executors.newFixedThreadPool(2);
        mtask1.executeOnExecutor(pool);
        
        mtask2.executeOnExecutor(pool);

 

我们创建了一个固定大小线程池,两个线程同时在池中运行(阻塞在doinbackground函数中),结果如下:

 

转载于:https://www.cnblogs.com/anshon/p/4735083.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值