Android多线程:AsyncTask的分析
开发Android应用的过程中,我们需要时刻注意保障应用的稳定性和界面响应性,因为不稳定或者响应速度慢的应用将会给用户带来非常差的交互体验。在越来越讲究用户体验的大环境下,用户也许会因为应用的一次Force Close(简称FC)或者延迟严重的动画效果而卸载你的应用。由于现在的应用大多需要异步连接网络,所以以构建网络应用为例,从稳定性和响应性两个角度分析多线程网络任务的性能优化方法。
为了不阻塞UI线程(亦称主线程),提高应用的响应性,我们经常会使用新开线程的方式,异步处理那些导致阻塞的任务。
AsyncTask是Android为我们提供的方便编写异步任务的工具类,但是,在了解AsyncTask的实现原理之后,发现AsyncTask并不能满足我们所有的需求,使用不当还有可能导致应用FC。
本文主要通过分析AsyncTask提交任务的策略和一个具体的例子,说明AsyncTask的不足之处
分析:
AsyncTask类包含一个全局静态的线程池,线程池的配置参数如下:
Java代码
1.private static final int CORE_POOL_SIZE =5;//5个核心工作线程
2. private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程
3. private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒
4.
5. private static final BlockingQueue<Runnable> sWorkQueue =
6. new LinkedBlockingQueue<Runnable>(10);//等待队列
7.
8. private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
9. MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。
private static final int CORE_POOL_SIZE =5;//5个核心工作线程
private static final int MAXIMUM_POOL_SIZE = 128;//最多128个工作线程
private static final int KEEP_ALIVE = 1;//空闲线程的超时时间为1秒
private static final BlockingQueue<Runnable> sWorkQueue =
new LinkedBlockingQueue<Runnable>(10);//等待队列
private static final ThreadPoolExecutorsExecutor = new ThreadPoolExecutor(CORE_POOL_SIZE,
MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sWorkQueue,sThreadFactory);//线程池是静态变量,所有的异步任务都会放到这个线程池的工作线程内执行。
我们这里不详细讲解ThreadPoolExecutor的原理,但将会讲解一个异步任务提交到AsyncTask的线程池时可能会出现的4种情况,并会提出在Android硬件配置普遍较低这个客观条件下,每个情况可能会出现的问题。
1、线程池中的工作线程少于5个时,将会创建新的工作线程执行异步任务(红色表示新任务,下同)
2、线程池中已经有5个线程,缓冲队列未满,异步任务将会放到缓冲队列中等待
3、线程池中已经有5个线程,缓冲队列已满,那么线程池将新开工作线程执行异步任务
问题:Android的设备一般不超过2个cpu核心,过多的线程会造成线程间切换频繁,消耗系统资源。
4、线程池中已经有128个线程,缓冲队列已满,如果此时向线程提交任务,将会抛出RejectedExecutionException
问题:抛出的错误不catch的话会导致程序FC。
好吧,理论分析之后还是要结合实际例子,我们通过实现一个模拟异步获取网络图片的例子,看看会不会出现上面提到的问题。
例子:使用GridView模拟异步加载大量图片
Activitya.java代码
1. package cn.caiwb;
2.
3. import java.util.ArrayList;
4. import java.util.Collection;
5. import java.util.HashMap;
6. import java.util.Iterator;
7. import java.util.List;
8. import java.util.ListIterator;
9. import java.util.Map;
10.
11.
12. import android.app.Activity;
13. import android.app.AlertDialog;
14. import android.app.Dialog;
15. import android.app.ListActivity;
16. import android.app.ProgressDialog;
17. import android.content.Context;
18. import android.content.DialogInte易做图ce;
19. import android.content.Intent;
20. import android.database.Cursor;
21. import android.graphics.Bitmap;
22. import android.os.AsyncTask;
23. import android.os.Bundle;
24. import android.provider.ContactsContract;
25. import android.util.Log;
26. import android.view.LayoutInflater;
27. import android.view.View;
28. import android.view.ViewGroup;
29. import android.widget.AbsListView;
30. import android.widget.AbsListView.OnScrollListener;
31. import android.widget.Adapter;
32. import android.widget.AdapterView;
33. import android.widget.AdapterView.OnItemClickListener;
34. import android.widget.BaseAdapter;
35. import android.widget.GridView;
36. import android.widget.ImageView;
37. import android.widget.ListAdapter;
38. import android.widget.SimpleAdapter;
39. import android.widget.TextView;
40. import android.widget.Toast;
41.
42. public class ActivityA extends Activity {
43.
44.
45. private GridView mGridView;
46. private List<HashMap<String, Object>> mData;
47.
48. private BaseAdapter mAdapter;
49. private ProgressDialog mProgressDialog;
50.
51. private static final int DIALOG_PROGRESS = 0;
52.
53. @Override
54. public void onCreate(Bundle savedInstanceState) {
55. super.onCreate(savedInstanceState);
56. setContentView(R.layout.main);
57. mGridView = (GridView) findViewById(R.id.gridview);
58. mData = new ArrayList<HashMap<String,Object>>();
59. mAdapter = new CustomAdapter();
60.
61.
62. mGridView.setAdapter(mAdapter);
63. }
64.
65. protecte
补充:移动开发 , Android ,