# 线程池和AsyncTask **Repository Path**: huangxiaoguo/XianChengChiHeAsyncTask ## Basic Information - **Project Name**: 线程池和AsyncTask - **Description**: 详细介绍了线程池和AsyncTask的原理,和使用简例,可快速引入项目进行使用. - **Primary Language**: Android - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2017-11-23 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 线程池和AsyncTask 详细介绍了线程池和AsyncTask的原理,和使用简例,可快速引入项目进行使用. AsyncTask --------- **3.1之前:** - 2.3系统同时execute执行10个异步任务 - 2.3到3.1版本之前的系统默认最大并发执行5个线程,缓冲线程队列最大128个。虽然开了10个异步任务, 但是只能同时并发执行5个,其他的任务都得等前面5个执行完后才继续执行,接着也是5次并发执行。 **3.1版本之后** - 默认是使用SERIAL_EXECUTOR串行任务执行,可以预料到异步任务将会是一个个顺序执行一个个线程按加入顺序同步执行的。也就是说,线程池中只有一个核心线程在工作, 其他线程都要等之前的线程执行完才能执行 - 使用默认提供的AsyncTask.THREAD_POOL_EXECUTOR线程池,最大并发执行5个线程,后面的线程都只能等之前5个结束之后再执行。 **onPreExecute()方法** 在execute(Params... params)被调用后立即执行, 一般用来在执行后台任务前对UI做一些标记。(准备工作) **doInBackground()方法** 在onPreExecute()完成后立即执行,用于执行较为费时的操作,此方法将接收输入参数和返回计算结果。 在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。(主线程中执行。 **onProgressUpdate()方法** 在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。 (主线程中执行,当后台任务的执行进度发送改变时此方法会被调用). **onPostExecute()方法** 当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中, 直接将结果显示到UI组件上。 (异步执行后这个方法被调用) **代码示例(有详细的注释):** ``` package tsou.cn.threadtest; import android.app.ProgressDialog; import android.os.AsyncTask; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.widget.TextView; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class AsyncTaskActivity extends AppCompatActivity { /** * TextView */ private TextView mTextView; private AsyncTask task; private ProgressDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_async_task); initData(); initView(); // initExecute(); // initExecuteOnExecutor(); initMyExecute(); } private void initData() { progressDialog = new ProgressDialog(AsyncTaskActivity.this); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setMessage("加载中..."); } private void initView() { mTextView = (TextView) findViewById(R.id.textView); } /** * 默认AsyncTask.SERIAL_EXECUTOR * 2.3系统同时execute执行10个异步任务 * 3.1版本之前的系统默认最大并发执行5个线程,缓冲线程队列最大128个。虽然开了10个异步任务, * 但是只能同时并发执行5个,其他的任务都得等前面5个执行完后才继续执行,接着也是5次并发执行。 *

* 3.1版本之后系统,默认是使用SERIAL_EXECUTOR串行任务执行, * 可以预料到异步任务将会是一个个顺序执行 *

* 一个个线程按加入顺序同步执行的。也就是说,线程池中只有一个核心线程在工作, * 其他线程都要等之前的线程执行完才能执行 */ private void initExecute() { String url = "http://blog.csdn.net/huangxiaoguo1"; task = new MyAsyncTask().execute(url); } /** * 自定义线程池执行,仅支持3.1以上系统 *

* 使用默认提供的AsyncTask.THREAD_POOL_EXECUTOR线程池 *

* 最大并发执行5个线程,后面的线程都只能等之前5个结束之后再执行 */ private void initExecuteOnExecutor() { String url = "http://blog.csdn.net/huangxiaoguo1"; task = new MyAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, url); } /** * 自定义线程池, *

* 10个核心任务并发执行,而且缓存队列最多能够存储100个任务, * 当队列满了之后还可以创建10个运行线程 *

* corePoolSize 核心线程池大小 * maximumPoolSize 线程池最大容量大小 * keepAliveTime 线程池空闲时,线程存活的时间 * TimeUnit 时间单位 * ThreadFactory 线程工厂 * BlockingQueue任务队列 * RejectedExecutionHandler 线程拒绝策略 */ private void initMyExecute() { String url = "http://blog.csdn.net/huangxiaoguo1"; Executor myExecutor = new ThreadPoolExecutor(5, 50, 10, TimeUnit.SECONDS, new LinkedBlockingDeque(100)); //ExecutorService executorService = Executors.newFixedThreadPool(3); /** * myExecutor也可以为newCachedThreadPool,newFixedThreadPool, * newScheduledThreadPool,newSingleThreadExecutor */ task = new MyAsyncTask().executeOnExecutor(myExecutor, url); } public class MyAsyncTask extends AsyncTask { /** * 在execute(Params... params)被调用后立即执行, * 一般用来在执行后台任务前对UI做一些标记。(准备工作) */ @Override protected void onPreExecute() { //后台执行先回调 super.onPreExecute(); progressDialog.show(); } /** * 在onPreExecute()完成后立即执行,用于执行较为费时的操作, * 此方法将接收输入参数和返回计算结果。 * 在执行过程中可以调用publishProgress(Progress... values)来更新进度信息。(主线程中执行 * * @param strings * @return */ @Override protected StringBuilder doInBackground(String... strings) {//对应第一个参数 //后台处理操作,不能修改UI if (isCancelled())//Task被取消了,马上退出循环 return null; try { URL url = new URL(strings[0]); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setReadTimeout(30000); conn.setConnectTimeout(30000); int code = conn.getResponseCode(); if (code == 200) { InputStream inputStream = conn.getInputStream(); InputStreamReader inputReader = new InputStreamReader(inputStream); BufferedReader reader = new BufferedReader(inputReader); StringBuilder stringBuilder = new StringBuilder(); while (true) { String readLine = reader.readLine(); if (readLine != null) { stringBuilder.append(readLine); } else { break; } } reader.close(); inputReader.close(); conn.disconnect(); return stringBuilder; } } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return null;//对应第三个参数 } /** * 在调用publishProgress(Progress... values)时,此方法被执行,直接将进度信息更新到UI组件上。 * (主线程中执行,当后台任务的执行进度发送改变时此方法会被调用). * * @param values */ @Override protected void onProgressUpdate(Integer... values) {//对应第二个参数 //后台任务,不能直接修改UI super.onProgressUpdate(values); if (isCancelled()) //Task被取消了,不再继续执行后面的代码 return; progressDialog.setProgress(values[0]); } /** * 当后台操作结束时,此方法将会被调用,计算结果将做为参数传递到此方法中, * 直接将结果显示到UI组件上。(异步执行后这个方法被调用) * * @param s */ @Override protected void onPostExecute(StringBuilder s) {//对应第三个参数 //后台任务完成后回调,更新UI super.onPostExecute(s); if (isCancelled()) //Task被取消了,不再继续执行后面的代码 return; progressDialog.dismiss(); if (s != null) mTextView.setText(s); } @Override protected void onCancelled() { //取消时回调 progressDialog.dismiss(); super.onCancelled(); } // @Override // protected void onCancelled(String s) {//对应第三个参数 // super.onCancelled(s); // } } @Override protected void onDestroy() { //取消异步任务代码 if (task != null && task.getStatus() == AsyncTask.Status.RUNNING) { task.cancel(true); } super.onDestroy(); } } ``` 线程池 --- **线程池一、newFixedThreadPool** ``` package tsou.cn.threadtest; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /*** * newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待 * * 每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。 * 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束, * 那么线程池会补充一个新线程。 */ public class NewFixedThreadPoolActivity extends AppCompatActivity implements View.OnClickListener { /** * 开始 */ private Button mStart; private ExecutorService fixedThreadPool; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_btn); initData(); initView(); } private void initData() { fixedThreadPool = Executors.newFixedThreadPool(3); } private void initView() { mStart = (Button) findViewById(R.id.start); mStart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: break; case R.id.start: for (int i = 0; i < 20; i++) { final int m = i; fixedThreadPool.execute(new Runnable() { @Override public void run() { /** * 因为线程池大小为3,每个任务输出index后sleep 2秒,所以每两秒打印3个数字。 定长线程池的大小最好根据系统资源进行设置。 */ if (fixedThreadPool.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo" + m); SystemClock.sleep(2000); } }); } break; } } /** * 停止线程工作 */ @Override protected void onDestroy() { super.onDestroy(); //threadPool 不能为空 threadPool 没有崩溃 threadPool 没有停止 if (fixedThreadPool != null && !fixedThreadPool.isShutdown() && !fixedThreadPool.isTerminated()) { fixedThreadPool.shutdownNow(); } } } ``` **线程池二、newScheduledThreadPool** ``` package tsou.cn.threadtest; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; /** *

* 创建一个大小无限的线程池。此线程池支持定时以及周期性执行任务的需求。 */ public class NewScheduledThreadPoolActivity extends AppCompatActivity implements View.OnClickListener { /** * 开始 */ private Button mStart; private ScheduledExecutorService scheduledThreadPool; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_btn); initData(); initView(); } private void initData() { scheduledThreadPool = Executors.newScheduledThreadPool(3); } private void initView() { mStart = (Button) findViewById(R.id.start); mStart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: break; case R.id.start: // initPoolOne(); // initPoolTwo(); initPoolThree(); break; } } /** * 表示延迟2秒后每3秒执行一次 */ private void initPoolThree() { scheduledThreadPool.scheduleWithFixedDelay(new Runnable() { @Override public void run() { if (scheduledThreadPool.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo"); } }, 2, 3, TimeUnit.SECONDS); } /** * 表示延迟2秒后每3秒执行一次 */ private void initPoolTwo() { scheduledThreadPool.scheduleAtFixedRate(new Runnable() { @Override public void run() { if (scheduledThreadPool.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo"); } }, 2, 3, TimeUnit.SECONDS); } /** * 表示延迟2秒后执行 */ private void initPoolOne() { scheduledThreadPool.schedule(new Runnable() { @Override public void run() { if (scheduledThreadPool.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo"); } }, 2, TimeUnit.SECONDS); } /** * 停止线程工作 */ @Override protected void onDestroy() { super.onDestroy(); //threadPool 不能为空 threadPool 没有崩溃 threadPool 没有停止 if (scheduledThreadPool != null && !scheduledThreadPool.isShutdown() &&!scheduledThreadPool.isTerminated()) { scheduledThreadPool.shutdownNow(); } } } ``` **线程池三、newCachedThreadPool** ``` package tsou.cn.threadtest; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 *

* 如果线程池的大小超过了处理任务所需要的线程, * 那么就会回收部分空闲(60秒不执行任务)的线程,当任务数增加时, * 此线程池又可以智能的添加新线程来处理任务。 * 此线程池不会对线程池大小做限制, * 线程池大小完全依赖于操作系统(或者说JVM)能够创建的最大线程大小。 */ public class NewCachedThreadPoolActivity extends AppCompatActivity implements View.OnClickListener { /** * 开始 */ private Button mStart; private ExecutorService cachedThreadPool; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_btn); initData(); initView(); } private void initData() { cachedThreadPool = Executors.newCachedThreadPool(); } private void initView() { mStart = (Button) findViewById(R.id.start); mStart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: break; case R.id.start: for (int i = 0; i < 20; i++) { final int m = i; cachedThreadPool.execute(new Runnable() { @Override public void run() { SystemClock.sleep(2000); if (cachedThreadPool.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo" + m); } }); } break; } } /** * 停止线程工作 */ @Override protected void onDestroy() { super.onDestroy(); //threadPool 不能为空 threadPool 没有崩溃 threadPool 没有停止 if (cachedThreadPool != null && !cachedThreadPool.isShutdown() &&!cachedThreadPool.isTerminated()) { cachedThreadPool.shutdownNow(); } } } ``` **线程池四、newSingleThreadExecutor** ``` package tsou.cn.threadtest; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务, * 保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行 *

* 这个线程池只有一个线程在工作,也就是相当于单线程串行执行>所有任务。 * 如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。 * 此线程池>保证所有任务的执行顺序按照任务的提交顺序执行。 */ public class NewSingleThreadExecutorActivity extends AppCompatActivity implements View.OnClickListener { /** * 开始 */ private Button mStart; private ExecutorService singleThreadExecutor; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_btn); initData(); initView(); } private void initData() { singleThreadExecutor = Executors.newSingleThreadExecutor(); } private void initView() { mStart = (Button) findViewById(R.id.start); mStart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: break; case R.id.start: for (int i = 0; i < 20; i++) { final int m = i; singleThreadExecutor.execute(new Runnable() { @Override public void run() { SystemClock.sleep(2000); if (singleThreadExecutor.isShutdown()) { return; } Log.e("huangxiaoguo", "huangxiaoguo" + m); } }); } break; } } /** * 停止线程工作 */ @Override protected void onDestroy() { super.onDestroy(); //threadPool 不能为空 threadPool 没有崩溃 threadPool 没有停止 if (singleThreadExecutor != null && !singleThreadExecutor.isShutdown() && !singleThreadExecutor.isTerminated()) { singleThreadExecutor.shutdownNow(); } } } ``` 自定义线程池工具类(代码中有详细注释) ---------- **创建线程池管理类** ``` package tsou.cn.threadtest.manager; import android.annotation.SuppressLint; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * 线程池管理 * * @author huangxiaoguo */ public class ThreadPoolManager { private ThreadPoolManager() { } // 饿汉式 线程安全 private static ThreadPoolManager instance = new ThreadPoolManager(); private PoolProxy longPoolProxy; // 给联网使用的线程池 private PoolProxy shortPoolProxy; // 读写文件使用的线程池 public static ThreadPoolManager getInstance() { return instance; } // 联网 // 读写文件 // 效率最高 cpu 核心数 *2+1 // 1 *2+1 public PoolProxy createLongThreadPool() { if (longPoolProxy == null) { longPoolProxy = new PoolProxy(5, 5, 5000); } return longPoolProxy; } public PoolProxy createShortThreadPool() { if (shortPoolProxy == null) { shortPoolProxy = new PoolProxy(3, 3, 5000); } return shortPoolProxy; } /** * 配置线程池 代理类 ThreadPoolExecutor 线程池 * * @author wxj */ public class PoolProxy { private int corePoolSize; private int maximumPoolSize; private long time; private ThreadPoolExecutor threadPool; // 线程池 public PoolProxy(int corePoolSize, int maximumPoolSize, long time) { super(); this.corePoolSize = corePoolSize; this.maximumPoolSize = maximumPoolSize; this.time = time; } @SuppressLint("NewApi") public void execute(Runnable r) { /** * 1.corePoolSize 初始化线程数量 2.maximumPoolSize 出了初始化 线程数量 另外最多 能创建的线程数量 * 3.keepAliveTime 如果没有任务 最多的存活时间 4. TimeUnit时间单位 */ if (threadPool == null) { // 当线程池 为空的时候才去创建 threadPool = new ThreadPoolExecutor(corePoolSize, maximumPoolSize, time, TimeUnit.MILLISECONDS, new LinkedBlockingDeque(10)); } // 就直接执行任务 threadPool.execute(r); } /** * 注意在需要取消任务的时候,不要使用shutdown(),或者shutdownNow(); * 来终止当前任务,因为你终止了当前任务,那样当前线程池还是存在的, * 再向线程池提交任务的时候,可能会因为队列已满,出现RejectedExecutionException *

* 所以使用remove方法移除当前任务来达到取消任务的效果, *

* 获取时线程队列使用getQueue()方法 */ public void cancel() { // threadPool 不能为空 threadPool 没有崩溃 threadPool 没有停止 if (threadPool != null && !threadPool.isShutdown() && !threadPool.isTerminated()) { BlockingQueue queue = threadPool.getQueue(); for (Runnable r : queue) { threadPool.remove(r); } } } } } ``` **封装ThreadUtils** ``` package tsou.cn.threadtest.utils; import android.os.Handler; import tsou.cn.threadtest.manager.ThreadPoolManager; public class ThreadUtils { private static ThreadPoolManager.PoolProxy longThreadPool; private static ThreadPoolManager.PoolProxy shortThreadPool; /** * 子线程执行 给联网 ... 特别耗时的 操作使用 * * @param r */ public static void runOnLongBackThread(Runnable r) { longThreadPool = ThreadPoolManager.getInstance().createLongThreadPool(); longThreadPool.execute(r); } /** * 子线程执行 给相对联网 耗时少的操作使用 * * @param r */ public static void runOnShortBackThread(Runnable r) { shortThreadPool = ThreadPoolManager.getInstance().createShortThreadPool(); shortThreadPool.execute(r); } /** * 取消给联网 ... 特别耗时的任务 */ public static void cancelLongBackThread() { if (longThreadPool != null) { longThreadPool.cancel(); } } /** * 取消给相对联网 耗时少的操作使用时的任务 */ public static void cancelShortThread() { if (shortThreadPool != null) { shortThreadPool.cancel(); } } private static Handler handler = new Handler(); /** * 在主线程执行 * * @param r */ public static void runOnUiThread(Runnable r) { handler.post(r); } } ``` **使用示例:** ``` package tsou.cn.threadtest; import android.os.Bundle; import android.os.SystemClock; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import tsou.cn.threadtest.utils.ThreadUtils; /*** * 自定义线程池 */ public class MyhreadPoolActivity extends AppCompatActivity implements View.OnClickListener { /** * 开始 */ private Button mStart; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_btn); initView(); } private void initView() { mStart = (Button) findViewById(R.id.start); mStart.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { default: break; case R.id.start: for (int i = 0; i < 10; i++) {//不能超过最大队列缓存数,不然崩溃(我的ThreadPoolManager最大缓存队列为10) final int m = i; ThreadUtils.runOnLongBackThread(new Runnable() { @Override public void run() { Log.e("huangxiaoguo", "huangxiaoguo" + m); SystemClock.sleep(2000); } }); } break; } } @Override protected void onDestroy() { super.onDestroy(); ThreadUtils.cancelLongBackThread(); } } ``` 我的博客:http://blog.csdn.net/huangxiaoguo1/article/details/78614842