标签:
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函数中),结果如下:
标签:
原文地址:http://www.cnblogs.com/anshon/p/4735083.html