yinbaoshiguang 2019-07-01
线程是CPU调度的最小单位。当一个程序第一次启动的时候,Android 会启动一个 Linux 进程和一个主线程。Android 中所有的组件都在主线程中实例化。主线程主要负责处理 UI 相关的事件,所以又被叫做 UI 线程。在 Android 中主线程是不能够做耗时操作的,子线程是不能够更新UI的。
与进程的区别:
优点:实现简单,只要继承 Thread 类,并重写 run 方法就可以实现多线程。
缺点:
具体使用:
// 步骤1:创建线程类 (继承自Thread类) class MyThread extends Thread{ @Override public void run(){ // 步骤2:从写run方法 } } // 步骤3:创建线程对象,即 实例化线程类 MyThread mt=new MyThread(“线程名称”); // 步骤4:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起 / 停止 mt.start();
可复用,代码量大
使用匿名类:
new Thread("线程名称") { @Override public void run() { // doSomeThing }.start();
不可复用,简介
注意:Thread 调用 run() 方法,就是一个普通的方法,失去线程的特性;start() 方法才会启动一个线程。
优点:
Java中真正能创建新线程的只有Thread类对象。通过实现Runnable的方式,最终还是通过Thread类对象来创建线程。所以对于实现了Runnable接口的类,称为线程辅助类;Thread类才是真正的线程类。
具体使用:
// 步骤1:创建线程辅助类,实现Runnable接口 class MyRunnable implements Runnable{ @Override // 步骤2:复写run(),定义线程行为 public void run(){ } } // 步骤3:创建线程辅助对象,即 实例化 线程辅助类 MyRunnable mr=new MyRunnable(); // 步骤4:创建线程对象,即 实例化线程类;线程类 = Thread类;创建时通过Thread类的构造函数传入线程辅助类对象 Thread td=new Thread(mr); // 步骤5:通过 线程对象 控制线程的状态,如 运行、睡眠、挂起 / 停止 td.start();
使用匿名类:
Runnable mt = new Runnable() { @Override public void run() { } }; Thread mt1 = new Thread(mt, "窗口1"); mt1.start();
作用:
实现工作线程 & 主线程(UI线程)之间的通信,即:将工作线程的执行结果传递给主线程,从而在主线程中执行相关的UI操作。从而保证线程安全。
优点:
缺点:
虽然 AsyncTask 的任务执行是通过线程池,线程池的核心线程,非核心线程规格大于1,但是后台运行的线程也只有一个,这是因为 AsyncTask 的任务管理线程池是 串行的 即,执行完一个任务才会执行下一个任务。
类定义:
public abstract class AsyncTask<Params, Progress, Result> { ... } // 类中参数为3种泛型类型 // 整体作用:控制AsyncTask子类执行线程任务时各个阶段的返回类型 // 具体说明: // a. Params:开始异步任务执行时传入的参数类型,对应excute()中传递的参数 // b. Progress:异步任务执行过程中,返回下载进度值的类型 // c. Result:异步任务执行完成后,返回的结果类型,与doInBackground()的返回值类型保持一致 // 注: // a. 使用时并不是所有类型都被使用 // b. 若无被使用,可用java.lang.Void类型代替 // c. 若有不同业务,需额外再写1个AsyncTask的子类 }
AsyncTask 核心 & 常用的方法如下:
使用步骤:
注意:
if (myAsyncTask != null && myAsyncTask.getStatus() == Status.RUNNING) { //cancel方法只是将对应的AsyncTask标记为cancelt状态,并不是真正的取消线程的执行. myAsyncTask.cancel(true); }
// AsyncTask 自带的线程池 task1.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); task2.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); // MY_THREAD_POOL_EXECUTOR 为自定义的线程池 task1.executeOnExecutor(MY_THREAD_POOL_EXECUTOR); task2.executeOnExecutor(MY_THREAD_POOL_EXECUTOR); // 替换掉默认的 AsyncTask.SERIAL_EXECUTOR MyAsyncTask.setDefaultExecutor(MY_THREAD_POOL_EXECUTOR); new MyAsyncTask(mActivity, "Task#a ").execute("abc"); new MyAsyncTask(mActivity, "Task#b ").execute("abc");
demo连接:处理了AsyncTask串行、并行问题,自定义线程池,以及AsyncTask内存泄漏的问题
原理:
参考原文:Android 多线程:AsyncTask的原理 及其源码分析
Carson_Ho的原文地址:Android多线程:线程池ThreadPool 全面解析