多线程
- 应用程序(Application):为了完成特定任务,用某种语言编写的一组指令集合(一组静态代码)
- 进程(Process) :运行中的程序,系统调度与资源分配的一个独立单位,操作系统会为每个进程分配 一段内存空间,程序的依次动态执行,经理代码加载 -> 执行 -> 执行完毕的完整过程!
- 线程(Thread):比进程更小的执行单元,每个进程可能有多条线程,线程需要放在一个进程中才能执行! 线程是由程序负责管理的!!!而进程则是由系统进行调度的!!!
- 多线程概念(Multithreading):并行地执行多条指令,将CPU的时间片按照调度算法,分配给各个线程,实际上是分时执行的,只是这个切换的时间很短,用户感觉是同时而已!
线程池
- 好处
对多个线程进行统一地管理,避免资源竞争中出现的问题。
对线程进行复用,线程在执行完任务后不会立刻销毁,而会等待另外的任务,这样就不会频繁地创建、销毁线程和调用GC。
JAVA提供了一套完整的ExecutorService线程池创建的api,可创建多种功能不一的线程池,使用起来很方便。
- ThreadPoolExecutor 创建基本线程池
创建线程池,主要是利用ThreadPoolExecutor这个类,而这个类有几种构造方法,其中参数最多的一种构造方法如下:
/**
* corePoolSize: 该线程池中核心线程的数量
* maximumPoolSize:该线程池中最大线程数量
* keepAliveTime:是非核心线程空闲时要等待下一个任务到来的时间
* unit:上面时间属性的单位
* workQueue:任务队列,后面详述。
* threadFactory:线程工厂,可用于设置线程名字等等,一般无须设置该参数。
*/
public ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory) {
...
}
- 五种线程池
newFixedThreadPool(int):参数为核心线程数,只有核心线程,无非核心线程,并且阻塞队列无界,适用于执行长期任务
newCachedThreadPool():没有核心线程,只有非核心线程,并且每个非核心线程空闲等待的时间为60s,超过自动销毁,采用SynchronousQueue队列,适用于有大量需要立即执行的耗时少的任务的情况
newSingleThreadExecutor():单个核心线程的newFixedThreadPool(int)
newScheduledThreadPool(int):固定大小,线程存活时间无限制,可以支持定时及周期性任务执行,若所有线程均处于繁忙状态,对于新任务会进入DelayedWorkQueue队列中,这是一种按照超时时间排序的队列结构,适用于周期性执行任务的场景
newSingleThreadScheduledExecutor():上两者的结合
AsyncTask简介
- 是一个抽象类
- 指定三个泛型参数
Params:可用于在后台中使用
Progress:在界面上显示当前进度,指定进度单位
Result:作为返回值类型
- 定义方法
class DownloadTask extends AsyncTask<Void,Integer,Boolean>{...}
- 重写四个方法
onPreExecute():在后台任务开始执行前调用,用于进行界面上的初始化操作,比如显示一个进度条对话框等
doInBackground():在此处理所有的耗时任务,若要反馈进度,则调用publishProgress(Progress...)来完成
onProgressUpdate(Progress...):当调用publishProgress(Progress...)之后,会被调用,对UI进行操作,利用参数中的数值会界面元素进行相应的更新
onPostExecute(Result):当后台任务执行完毕并通过return语句进行返回,该方法很快会被调用
注意事项
- Task的实例必须在UIThread中创建
- execute方法必须在UIThread中调用
- 不要手动调用onPreExecute(),onPostExecute(Result),doInBackground(),onProgressUpdate(Progress...)这几个方法
- 该task只能被执行一次,否则多次调用会出现异常
实例
class DownloadTask extends AsyncTask<Void,Integer,Boolean> {
@Override
protected void onPreExecute() {
//显示进度对话框
progressDialog.show();
}
@Override
protected Boolean doInBackground(Void... params) {
try{
while (true) {
//这是一个虚构的方法
int downloadPercent = doDownload();
publishProgress(downloadPercent);
if (downloadPercent >=100){
break;
}
}
}
}
@Override
protected void onProgressUpdate(Integer... values) {
//在这里更新下载进度
progressDialog.setMessage("Downloaded " + values[0] + "%");
}
@Override
protected void onPostExecute(Boolean Result) {
//关闭进度对话框
progressDialog.dismiss();
//提示下载结果
if(result) {
Toast.makeText(context,"Download succeed",Toast.LENGTH_SHORT).show();
}else {
Toast.makeText(context,"Download failed",Toast.LENGTH_SHORT).show();
}
}
}