线程池三:AsyncTask线程池


1. AsyncTask介绍

AsyncTask能够适当地、简单地用于 UI线程。 这个类不需要操作线程(handlers)就可以完成后台操作将结果返回UI。

AsyncTask设计目的在于在framework层完成 Thread and Handler交互。Asyn应该被用在短操作上(数秒内完成)。如果需要保持线程运行长时间,相当推荐使用APIs提供的java.util.concurrent例如:ExecutorThreadPoolExecutor and FutureTask.

异步任务的定义是一个在后台线程上运行,其结果是在 UI线程上发布的计算。 异步任务被定义成三种泛型类型: Params,Progress和 Result;和四个步骤:  

  • onPreExecute

  • doInBackground,

  • onProgressUpdate

  • onPostExecute

2. AsyncTask线程池示例

AsyncTask是基于FutureTask封装的异步操作类支持                                                                                                                                 

(1)多线程串行模式执行:private ExecutorService SINGLE_TASK = Executors.newSingleThreadExecutor();

(2)多线程限制模式执行:private ExecutorService LIMITED_TASK = Executors.newFixedThreadPool(3);

(3)多线程并行模式执行:private ExecutorService FULL_TASK = Executors.newCachedThreadPool ();

(4)提供查询线程是否取消:isCancelled()

(5)支持线程取消:onCancelled(Result result)

(6)提供获取线程状态:getStatus()

AsyncTask在线程执行层面提供了三种方法                                                                                                                                                

(1)#execute()提交任务,按照先后顺序每次只运行一个。

也就是说它是按照提交的次序,每次只启动一个线程执行一个任务,完成之后在执行第二个任务,也就是相当于只有一个后台线程在执行所提交的任务类似于:Executors.newSingleThreadExecutor();

(2)#execute(Runnable runnable)提交任务,按照先后顺序每次只运行一个。参考(1

(3)#executeOnExecutor(Executor exec, Params... params)

这个接口允许开发者提供自定义的线程池来运行和调度Thread。如果你想让所有的任务都能同时并发运行,那就创建一个没有限制的线程池,参考上述:FULL_TASK,并提供给AsyncTask,这样这个AsyncTask实例就有了自己的线程池而不必使用AsyncTask默认的。同理可以使用LIMITED_TASK。

AsyncTask代码示例                                                                                                                                                                                  

代码将线程执行过程转化为可视化效果:

/**
 * 线程池二:使用AsyncTask实现线程池控制
 *
 *
 */
private void initViewAsync() {
    setContentView(R.layout. activity_thread_pool);
    mBar1 = (SeekBar) findViewById(R.id. seekBar1);
    mBar2 = (SeekBar) findViewById(R.id. seekBar2);
    mBar3 = (SeekBar) findViewById(R.id. seekBar3);
    mBar4 = (SeekBar) findViewById(R.id. seekBar4);
    mBar5 = (SeekBar) findViewById(R.id. seekBar5);
    mBar6 = (SeekBar) findViewById(R.id. seekBar6);
    mBar1.setMax(100);
    mBar2.setMax(100);
    mBar3.setMax(100);
    mBar4.setMax(100);
    mBar5.setMax(100);
    mBar6.setMax(100);
    MyAsynctask asyncTask1 = new MyAsynctask("bar1" );
    MyAsynctask asyncTask2 = new MyAsynctask("bar2" );
    MyAsynctask asyncTask3 = new MyAsynctask("bar3" );
    MyAsynctask asyncTask4 = new MyAsynctask("bar4" );
    MyAsynctask asyncTask5 = new MyAsynctask("bar5" );
    MyAsynctask asyncTask6 = new MyAsynctask("bar6" );
    asyncTask1.executeOnExecutor( FULL_TASK);
    asyncTask2.executeOnExecutor( FULL_TASK);
    asyncTask3.executeOnExecutor( FULL_TASK);
    asyncTask4.executeOnExecutor( FULL_TASK);
    asyncTask5.executeOnExecutor( FULL_TASK);
    asyncTask6.executeOnExecutor( FULL_TASK);
}

class MyAsynctask extends AsyncTask<Void, Integer, Void> {
   
    private String mKey = null;
    public MyAsynctask(String key) {
        mKey = key;
    }
    @Override
    protected Void doInBackground(Void... params) {
        if ("bar1" .equals(mKey )) {
            while (mBar1 .getProgress() < 100) {
                int i = mBar1 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar1 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        } else if ("bar2" .equals(mKey )) {
            while (mBar2 .getProgress() < 100) {
                int i = mBar2 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar2 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        } else if ("bar3" .equals(mKey )) {
            while (mBar3 .getProgress() < 100) {
                int i = mBar3 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar3 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        } else if ("bar4" .equals(mKey )) {
            while (mBar4 .getProgress() < 100) {
                int i = mBar4 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar4 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        } else if ("bar5" .equals(mKey )) {
            while (mBar5 .getProgress() < 100) {
                int i = mBar5 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar5 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        } else if ("bar6" .equals(mKey )) {
            while (mBar6 .getProgress() < 100) {
                int i = mBar6 .getProgress() + 1;
                if (0 == i % 10) {
                    Log. i(TAG, "mBar6 number:" + i );
                }
                try {
                    Thread. sleep(mTime);
                } catch (InterruptedException e ) {
                    e.printStackTrace();
                }
                publishProgress( i);
            }
        }
        return null ;
    }
   
    @Override
    protected void onPostExecute(Void result ) {
        Log. i(TAG, "onPostExecute");
    }
   
    @Override
    protected void onPreExecute() {
        Log. i(TAG, "onPreExecute");
    }
   
    @Override
    protected void onProgressUpdate(Integer... values ) {
        if ("bar1" .equals(mKey )) {
            mBar1.setProgress( values[0]);
        } else if ("bar2" .equals(mKey )) {
            mBar2.setProgress( mBar2.getProgress() + 1);
        } else if ("bar3" .equals(mKey )) {
            mBar3.setProgress( mBar3.getProgress() + 1);
        } else if ("bar4" .equals(mKey )) {
            mBar4.setProgress( mBar4.getProgress() + 1);
        } else if ("bar5" .equals(mKey )) {
            mBar5.setProgress( mBar5.getProgress() + 1);
        } else if ("bar6" .equals(mKey )) {
            mBar6.setProgress( mBar6.getProgress() + 1);
        }
    }
}

布局文件代码activity_thread_pool.xml:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#1"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#2"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#3"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#4"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#5"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar5"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
        <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:padding="10dp" >
        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Task#6"
            android:textAppearance="?android:attr/textAppearanceLarge" />
        <SeekBar
            android:id="@+id/seekBar6"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />
    </LinearLayout>
    <View
        android:layout_width="match_parent"
        android:layout_height="1px"
        android:background="#dddddd"/>
</LinearLayout>

执行效果:

3. AsyncTask源码分析

3.1变量定义

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;

private static final ThreadFactory sThreadFactory = new ThreadFactory() {
    private final AtomicInteger mCount = new AtomicInteger(1);

    public Thread newThread(Runnable r) {
        return new Thread(r , "AsyncTask #" + mCount .getAndIncrement());
    }
};

private static final BlockingQueue<Runnable> sPoolWorkQueue =
        new LinkedBlockingQueue<Runnable>(128);

/**
 * An {@link Executor} that can be used to execute tasks in parallel.
 */
public static final Executor THREAD_POOL_EXECUTOR
        = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE,
                TimeUnit. SECONDS, sPoolWorkQueue , sThreadFactory);

/**
 * An {@link Executor} that executes tasks one at a time in serial
 * order.  This serialization is global to a particular process.
 */
public static final Executor SERIAL_EXECUTOR = new SerialExecutor();

private static final int MESSAGE_POST_RESULT = 0x1;
private static final int MESSAGE_POST_PROGRESS = 0x2;

private static volatile Executor sDefaultExecutor = SERIAL_EXECUTOR;
private static InternalHandler sHandler;

private final WorkerRunnable<Params, Result> mWorker;
private final FutureTask<Result> mFuture;

private volatile Status mStatus = Status.PENDING;

private final AtomicBoolean mCancelled = new AtomicBoolean();
private final AtomicBoolean mTaskInvoked = new AtomicBoolean();
  • 声明中可以看出,变量THREAD_POOL_EXECUTORsHandler 都为静态变量static,为进程范围内共享的,属于类的作用范围是CLASSPATH,其中一个进程就是一个VM。

  • 声明中可以看出,变量sDefaultExecutormStatus 使用volatile关键字声明,volatile的作用是: 作为指令关键字,确保本条指令不会因编译器的优化而省略,且要求每次直接读值.

  • 声明中可以看出,变量mCancelled 和mTaskInvoked 类型为AtomicBoolean ,表示可以用原子方式更新的 boolean 值。有关原子变量属性的描述,请参阅 java.util.concurrent.atomic 包规范。AtomicBoolean 可用在应用程序中(如以原子方式更新的标志),但不能用于替换 Boolean。

3.2函数分

构造函数分析

/**
 * Creates a new asynchronous task. This constructor must be invoked on the UI thread.
 */
public AsyncTask() {
    mWorker = new WorkerRunnable<Params, Result>() {
        public Result call() throws Exception {
            mTaskInvoked.set(true );

            Process.setThreadPriority(Process. THREAD_PRIORITY_BACKGROUND);
            //noinspection unchecked
            Result result = doInBackground( mParams);
            Binder. flushPendingCommands();
            return postResult(result );
        }
    };

    mFuture = new FutureTask<Result>( mWorker) {
        @Override
        protected void done() {
            try {
                postResultIfNotInvoked(get());
            } catch (InterruptedException e ) {
                android.util.Log. w(LOG_TAG, e);
            } catch (ExecutionException e ) {
                throw new RuntimeException("An error occurred while executing doInBackground()",
                        e.getCause());
            } catch (CancellationException e ) {
                postResultIfNotInvoked( null);
            }
        }
    };
}

其中WorkRunnable实现Callable<Result>,可参考上篇博客:线程池二:Java并发编程:Callable、Future和FutureTask中的:使用Callable+FutureTask获取执行结果,call()函数为线程执行函数,将doInBackground()函数放入其中,执行后台函数。

    private static abstract class WorkerRunnable<Params, Result> implements Callable<Result> {
        Params[] mParams;
    }

执行函数分析

    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;
        // 线程前执行,UI线程
        onPreExecute();

        mWorker.mParams = params;
        // 执行mFuture
        exec.execute(mFuture);

        return this;
    }

    ...

    // 传递线程执行进度
    protected final void publishProgress(Progress... values) {
        if (!isCancelled()) {
            sHandler.obtainMessage(MESSAGE_POST_PROGRESS,
                    new AsyncTaskResult<Progress>(this, values)).sendToTarget();
        }
    }
    // 结束线程
    private void finish(Result result) {
        if (isCancelled()) {
            onCancelled(result);
        } else {
            // 线程结束调用
            onPostExecute(result);
        }
        mStatus = Status.FINISHED;
    }
    // handler处理操作
    private static class InternalHandler extends Handler {
        @SuppressWarnings({"unchecked", "RawUseOfParameterizedType"})
        @Override
        public void handleMessage(Message msg) {
            AsyncTaskResult result = (AsyncTaskResult) msg.obj;
            switch (msg.what) {
                case MESSAGE_POST_RESULT:
                    // There is only one result
                    result.mTask.finish(result.mData[0]);
                    break;
                case MESSAGE_POST_PROGRESS:
                    result.mTask.onProgressUpdate(result.mData);
                    break;
            }
        }
    }

上面代码中可见executeOnExecutor需要在主线程中执行,依次调用:

(1)UI线程调用onPreExecute() 

(2)线程中调用doInBackground( mParams)

(3)UI线程调用onProgressUpdate

(4)UI线程调用onPostExecute(result)

4. 参考资料


线程池二:Java并发编程:Callable、Future和FutureTask

AsyncTask|Android Developer

https://developer.xamarin.com/api/member/Android.OS.Binder.FlushPendingCommands()/




你可能感兴趣的:(线程池,AsyncTask,AsyncTask源码分析,AsyncTask异步线程)