Android线程池AsyncTask使用

  由于经常会在网上或群里看到有朋友会问线程方面的东西,就像我一个朋友他们师讲的,J2SE、J2EE里面使用的线程方面的东西可能不是太多 ,但是在Android开发里面,玩的就是线程(UI Thread)! 好了,废话就说这么多吧,直入正题!今天要讲的东西就是线程池、线程的高效率使用,灵活控制!今死马我就用最常用的几种方式来分别实现应用中使用的线程方面的知识,(共写了两个不同入口的Activity来分开不同的实现方式,大家可以自行注释AndroidManifest.xml中的Launch入口或打开注释)好了,先随便列几个吧,如:AsyncTask 、Runnable 、Thread、ThreadPool、 Executors等等的使用,先上效果,再一步步分解代码,来吧,效果图如下:

  一:无大小限制的线程池执行效果如下

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 1

 

  二:限制按顺序来执行任务的线程池效果如下

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 2

 

  三:一个一个任务的执行线程池效果如下(与按顺序执行效果是一样的,只是内部实现稍有不同)

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 3

 

  四:按指定个数来执行任务的线程池效果如下

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 4

 

  五:创建一个可在指定时间里执行任务的线程池,亦可重复执行,不常用,效果与四相同

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 5

 

 

  六:按指定工厂模式来执行的线程池,效果与四、五一样,但用方式六创建的线程池都有在工厂中指定的线程属性,比如:线程名字、是否为用户线程等等属性

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 6

 

  七:线程池中任务执行时可暂停效果图如下

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 7

 

 

  八:用Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现的效果图如下

  Android研究院之应用开发线程池的经典使用(二十九) - 雨松MOMO程序研究院 - 8

 

         哦了,效果看完了,现在就请大家自行修改AndroidManifest.xml中主Activity的入口来看两种不同方式实现的代码效果吧,首先,先贴一下Main.java类的代码,希望大家详细看里面的注释,一定要详细看,你不会吃亏的,相信我!(备注:为了写文章加注释还有查找的时候方便,我把所有的主类及辅助类以内部类的形式写到一个.java文件里面了,如果朋友们觉得看着乱,不爽的话,可以自行将里面的类抽取到单独的.java文件中,几分钟搞定的事!)

 

  方式一(纯ExecutorService、AsyncTask、Runnable关联实现相关文件如下):

 

  1.1:主类文件(Main.java)

  1 package com.xiaoma.threadpooltest;
  2  
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 import java.util.concurrent.ExecutorService;
  6 import java.util.concurrent.Executors;
  7 import java.util.concurrent.ThreadFactory;
  8  
  9 import android.annotation.TargetApi;
 10 import android.app.Activity;
 11 import android.content.Context;
 12 import android.os.AsyncTask;
 13 import android.os.Build;
 14 import android.os.Bundle;
 15 import android.os.SystemClock;
 16 import android.util.AttributeSet;
 17 import android.util.Log;
 18 import android.view.LayoutInflater;
 19 import android.view.View;
 20 import android.view.ViewGroup;
 21 import android.widget.AdapterView;
 22 import android.widget.AdapterView.OnItemClickListener;
 23 import android.widget.BaseAdapter;
 24 import android.widget.LinearLayout;
 25 import android.widget.ListView;
 26 import android.widget.ProgressBar;
 27 import android.widget.TextView;
 28 import android.widget.Toast;
 29  
 30 /**
 31  * @TODO [The Class File Description]
 32  * @author XiaoMaGuo ^_^
 33  * @version [version-code, 2013-10-15]
 34  * @since [Product/module]
 35  */
 36 @TargetApi(Build.VERSION_CODES.HONEYCOMB)
 37 public class Main extends Activity
 38 {
 39     private static int order = 0;
 40  
 41     /** 总共多少任务(根据CPU个数决定创建活动线程的个数,这样取的好处就是可以让手机承受得住) */
 42     // private static final int count = Runtime.getRuntime().availableProcessors() * 3 + 2;
 43  
 44     /** 总共多少任务(我是在模拟器里面跑的,为了效果明显,所以写死了为10个,如果在手机上的话,推荐使用上面的那个count) */
 45     private static final int count = 10;
 46  
 47     /** 每次只执行一个任务的线程池 */
 48     private static ExecutorService singleTaskExecutor = null;
 49  
 50     /** 每次执行限定个数个任务的线程池 */
 51     private static ExecutorService limitedTaskExecutor = null;
 52  
 53     /** 所有任务都一次性开始的线程池 */
 54     private static ExecutorService allTaskExecutor = null;
 55  
 56     /** 创建一个可在指定时间里执行任务的线程池,亦可重复执行 */
 57     private static ExecutorService scheduledTaskExecutor = null;
 58  
 59     /** 创建一个可在指定时间里执行任务的线程池,亦可重复执行(不同之处:使用工程模式) */
 60     private static ExecutorService scheduledTaskFactoryExecutor = null;
 61  
 62     private List<AsyncTaskTest> mTaskList = null;
 63  
 64     /** 任务是否被取消 */
 65     private boolean isCancled = false;
 66  
 67     /** 是否点击并取消任务标示符 */
 68     private boolean isClick = false;
 69  
 70     /** 线程工厂初始化方式一 */
 71     ThreadFactory tf = Executors.defaultThreadFactory();
 72  
 73     /** 线程工厂初始化方式二 */
 74     private static class ThreadFactoryTest implements ThreadFactory
 75     {
 76  
 77         @Override
 78         public Thread newThread(Runnable r)
 79         {
 80             Thread thread = new Thread(r);
 81             thread.setName("XiaoMaGuo_ThreadFactory");
 82             thread.setDaemon(true); // 将用户线程变成守护线程,默认false
 83             return thread;
 84         }
 85     }
 86  
 87     static
 88     {
 89         singleTaskExecutor = Executors.newSingleThreadExecutor();// 每次只执行一个线程任务的线程池
 90         limitedTaskExecutor = Executors.newFixedThreadPool(3);// 限制线程池大小为7的线程池
 91         allTaskExecutor = Executors.newCachedThreadPool(); // 一个没有限制最大线程数的线程池
 92         scheduledTaskExecutor = Executors.newScheduledThreadPool(3);// 一个可以按指定时间可周期性的执行的线程池
 93         scheduledTaskFactoryExecutor = Executors.newFixedThreadPool(3, new ThreadFactoryTest());// 按指定工厂模式来执行的线程池
 94         scheduledTaskFactoryExecutor.submit(new Runnable()
 95         {
 96  
 97             @Override
 98             public void run()
 99             {
100                 Log.i("KKK", "This is the ThreadFactory Test  submit Run! ! ! ");
101             }
102         });
103     };
104  
105     @Override
106     public void onCreate(Bundle icicle)
107     {
108         super.onCreate(icicle);
109         setContentView(R.layout.demo);
110         final ListView taskList = (ListView)findViewById(R.id.task_list);
111         taskList.setAdapter(new AsyncTaskAdapter(getApplication(), count));
112         taskList.setOnItemClickListener(new OnItemClickListener()
113         {
114  
115             @Override
116             public void onItemClick(AdapterView<?> parent, View view, int position, long id)
117             {
118                 if (position == 0) // 以第一项为例,来测试关闭线程池
119                 {
120                     /**
121                      * 会关闭线程池方式一:但不接收新的Task,关闭后,正在等待 执行的任务不受任何影响,会正常执行,无返回值!
122                      */
123                     // allTaskExecutor.shutdown();
124  
125                     /**
126                      * 会关闭线程池方式二:也不接收新的Task,并停止正等待执行的Task(也就是说, 执行到一半的任务将正常执行下去),最终还会给你返回一个正在等待执行但线程池关闭却没有被执行的Task集合!
127                      */
128                     List<Runnable> unExecRunn = allTaskExecutor.shutdownNow();
129  
130                     for (Runnable r : unExecRunn)
131                     {
132                         Log.i("KKK", "未执行的任务信息:=" + unExecRunn.toString());
133                     }
134                     Log.i("KKK", "Is shutdown ? = " + String.valueOf(allTaskExecutor.isShutdown()));
135                     allTaskExecutor = null;
136                 }
137  
138                 // 以第二项为例来测试是否取消执行的任务
139                 AsyncTaskTest sat = mTaskList.get(1);
140                 if (position == 1)
141                 {
142                     if (!isClick)
143                     {
144                         sat.cancel(true);
145                         isCancled = true;
146                         isClick = !isClick;
147                     }
148                     else
149                     {
150                         sat.cancel(false);
151                         isCancled = false;
152                         // isClick = false;
153                         isClick = !isClick;
154                         if (null != sat && sat.getStatus() == AsyncTask.Status.RUNNING)
155                         {
156                             if (sat.isCancelled())
157                             {
158                                 sat = new AsyncTaskTest(sat.mTaskItem);
159                             }
160                             else
161                             {
162                                 Toast.makeText(Main.this, "A task is already running, try later", Toast.LENGTH_SHORT)
163                                     .show();
164                             }
165                         }
166  
167                         /**
168                          * 由于上面测试关闭,在不重新生成allTaskExecutor的同时,会报异常(没有可以使用的线程池,故此处重新生成线程池对象)
169                          */
170                         if (allTaskExecutor == null)
171                         {
172                             allTaskExecutor = Executors.newCachedThreadPool();
173                         }
174                         sat.executeOnExecutor(allTaskExecutor); // The task is already running(这也是个异常哦,小心使用! )
175                     }
176                 }
177                 else
178                 {
179                     sat.cancel(false);
180                     isCancled = false;
181                     // sat.execute(sat.mTaskItem);
182                     // sat.executeOnExecutor(allTaskExecutor);
183                 }
184  
185             }
186         });
187     }
188  
189     /**
190      * @TODO [ListView Item的条目适配器]
191      * @author XiaoMaGuo ^_^
192      * @version [version-code, 2013-10-22]
193      * @since [Product/module]
194      */
195     private class AsyncTaskAdapter extends BaseAdapter
196     {
197         private Context mContext;
198  
199         private LayoutInflater mFactory;
200  
201         private int mTaskCount;
202  
203         public AsyncTaskAdapter(Context context, int taskCount)
204         {
205             mContext = context;
206             mFactory = LayoutInflater.from(mContext);
207             mTaskCount = taskCount;
208             mTaskList = new ArrayList<AsyncTaskTest>(taskCount);
209         }
210  
211         @Override
212         public int getCount()
213         {
214             return mTaskCount;
215         }
216  
217         @Override
218         public Object getItem(int position)
219         {
220             return mTaskList.get(position);
221         }
222  
223         @Override
224         public long getItemId(int position)
225         {
226             return position;
227         }
228  
229         @Override
230         public View getView(int position, View convertView, ViewGroup parent)
231         {
232             if (convertView == null)
233             {
234                 convertView = mFactory.inflate(R.layout.list_view_item, null);
235                 AsyncTaskTest task = new AsyncTaskTest((MyListItem)convertView);
236  
237                 /**
238                  * 下面两种任务执行效果都一样,形变质不变
239                  * */
240                 // task.execute();
241                 // task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
242  
243                 /**
244                  * 下面的方式在小于API 11级时效果是一样的,但在高版本中的稍微有点不同,可以看以下AsyncTask核心变量的定义就知道了使用如下
245                  * 方式时,系统会默认的采用五个一组,五个一组的方式来执行我们的任务,定义在:AsyncTask.class中,private static final int CORE_POOL_SIZE = 5;
246                  * */
247                 // use AsyncTask#THREAD_POOL_EXECUTOR is the same to older version #execute() (less than API 11)
248                 // but different from newer version of #execute()
249                 // task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
250  
251                 /**
252                  * 一个一个执行我们的任务,效果与按顺序执行是一样的(AsyncTask.SERIAL_EXECUTOR)
253                  * */
254                 // task.executeOnExecutor(singleTaskExecutor);
255  
256                 /**
257                  * 按我们指定的个数来执行任务的线程池
258                  * */
259                 // task.executeOnExecutor(limitedTaskExecutor);
260  
261                 /**
262                  * 不限定指定个数的线程池,也就是说:你往里面放了几个任务,他全部同一时间开始执行, 不管你手机受得了受不了
263                  * */
264                 task.executeOnExecutor(allTaskExecutor);
265  
266                 /**
267                  * 创建一个可在指定时间里执行任务的线程池,亦可重复执行
268                  * */
269                 // task.executeOnExecutor(scheduledTaskExecutor);
270  
271                 /**
272                  * 创建一个按指定工厂模式来执行任务的线程池,可能比较正规,但也不常用
273                  */
274                 // task.executeOnExecutor(scheduledTaskFactoryExecutor);
275                 mTaskList.add(task);
276             }
277             return convertView;
278         }
279     }
280  
281     class AsyncTaskTest extends AsyncTask<Void, Integer, Void>
282     {
283         private MyListItem mTaskItem;
284  
285         private String id;
286  
287         private AsyncTaskTest(MyListItem item)
288         {
289             mTaskItem = item;
290             if (order < count || order == count)
291             {
292                 id = "执行:" + String.valueOf(++order);
293             }
294             else
295             {
296                 order = 0;
297                 id = "执行:" + String.valueOf(++order);
298             }
299         }
300  
301         @Override
302         protected void onPreExecute()
303         {
304             mTaskItem.setTitle(id);
305         }
306  
307         /**
308          * Overriding methods
309          */
310         @Override
311         protected void onCancelled()
312         {
313             super.onCancelled();
314         }
315  
316         @Override
317         protected Void doInBackground(Void... params)
318         {
319             if (!isCancelled() && isCancled == false) // 这个地方很关键,如果不设置标志位的话,直接setCancel(true)是无效的
320             {
321                 int prog = 0;
322  
323                 /**
324                  * 下面的while中,小马写了个分支用来做个假象(任务东西刚开始下载的时候,速度快,快下载完成的时候就突然间慢了下来的效果, 大家可以想象一下,类似
325                  * :PP手机助手、91手机助手中或其它手机应用中,几乎都有这个假象,开始快,结束时就下载变慢了,讲白了 就是开发的人不想让你在下载到大于一半的时候,也就是快下载完的时候去点取消,你那样得多浪费
326                  * !所以造个假象,让你不想去取消而已)
327                  */
328                 while (prog < 101)
329                 {
330  
331                     if ((prog > 0 || prog == 0) && prog < 70) // 小于70%时,加快进度条更新
332                     {
333                         SystemClock.sleep(100);
334                     }
335                     else
336                     // 大于70%时,减慢进度条更新
337                     {
338                         SystemClock.sleep(300);
339                     }
340  
341                     publishProgress(prog); // 更新进度条
342                     prog++;
343                 }
344             }
345             return null;
346         }
347  
348         @Override
349         protected void onPostExecute(Void result)
350         {
351         }
352  
353         @Override
354         protected void onProgressUpdate(Integer... values)
355         {
356             mTaskItem.setProgress(values[0]); // 设置进度
357         }
358     }
359 }
360  
361 /**
362  * @TODO [一个简单的自定义 ListView Item]
363  * @author XiaoMaGuo ^_^
364  * @version [version-code, 2013-10-22]
365  * @since [Product/module]
366  */
367 class MyListItem extends LinearLayout
368 {
369     private TextView mTitle;
370  
371     private ProgressBar mProgress;
372  
373     public MyListItem(Context context, AttributeSet attrs)
374     {
375         super(context, attrs);
376     }
377  
378     public MyListItem(Context context)
379     {
380         super(context);
381     }
382  
383     public void setTitle(String title)
384     {
385         if (mTitle == null)
386         {
387             mTitle = (TextView)findViewById(R.id.task_name);
388         }
389         mTitle.setText(title);
390     }
391  
392     public void setProgress(int prog)
393     {
394         if (mProgress == null)
395         {
396             mProgress = (ProgressBar)findViewById(R.id.task_progress);
397         }
398         mProgress.setProgress(prog);
399     }
400 }

 

  

  1.2:布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2   <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3       android:layout_width="match_parent"
 4       android:layout_height="match_parent"
 5       android:paddingLeft="10dip"
 6       android:paddingRight="10dip"
 7       android:orientation="vertical" >
 8       <ListView android:id="@+id/task_list"
 9           android:layout_width="fill_parent"
10          android:layout_height="wrap_content"
11          android:divider="#cccccc"
12          android:dividerHeight="0.6dip"
13          android:footerDividersEnabled="true"
14          android:headerDividersEnabled="true" />
15  </LinearLayout>

 

 

 

  方式二(Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现的相关文件如 下):

  

  2.1:主类文件(MyRunnableActivity.java)

  1 package com.xiaoma.threadpooltest;
  2  
  3 import java.util.Iterator;
  4 import java.util.Map;
  5 import java.util.concurrent.ConcurrentHashMap;
  6 import java.util.concurrent.ConcurrentLinkedQueue;
  7 import java.util.concurrent.ConcurrentMap;
  8 import java.util.concurrent.ExecutorService;
  9 import java.util.concurrent.Executors;
 10 import java.util.concurrent.Future;
 11  
 12 import android.app.Activity;
 13 import android.os.Bundle;
 14 import android.os.Handler;
 15 import android.os.Message;
 16 import android.util.Log;
 17 import android.view.View;
 18 import android.view.View.OnClickListener;
 19 import android.widget.ProgressBar;
 20 import android.widget.Toast;
 21  
 22 /**
 23  * @TODO [线程池控制 ]
 24  * @author XiaoMaGuo ^_^
 25  * @version [version-code, 2013-10-22]
 26  * @since [Product/module]
 27  */
 28 public class MyRunnableActivity extends Activity implements OnClickListener
 29 {
 30  
 31     /** 任务执行队列 */
 32     private ConcurrentLinkedQueue<MyRunnable> taskQueue = null;
 33  
 34     /**
 35      * 正在等待执行或已经完成的任务队列
 36      * 
 37      * 备注:Future类,一个用于存储异步任务执行的结果,比如:判断是否取消、是否可以取消、是否正在执行、是否已经完成等
 38      * 
 39      * */
 40     private ConcurrentMap<Future, MyRunnable> taskMap = null;
 41  
 42     /**
 43      * 创建一个不限制大小的线程池 此类主要有以下好处 1,以共享的无界队列方式来运行这些线程. 2,执行效率高。 3,在任意点,在大多数 nThreads 线程会处于处理任务的活动状态
 44      * 4,如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。
 45      * 
 46      * */
 47     private ExecutorService mES = null;
 48  
 49     /** 在此类中使用同步锁时使用如下lock对象即可,官方推荐的,不推荐直接使用MyRunnableActivity.this类型的,可以详细读一下/framework/app下面的随便一个项目 */
 50     private Object lock = new Object();
 51  
 52     /** 唤醒标志,是否唤醒线程池工作 */
 53     private boolean isNotify = true;
 54  
 55     /** 线程池是否处于运行状态(即:是否被释放!) */
 56     private boolean isRuning = true;
 57  
 58     /** 任务进度 */
 59     private ProgressBar pb = null;
 60  
 61     /** 用此Handler来更新我们的UI */
 62     private Handler mHandler = null;
 63  
 64     /**
 65      * Overriding methods
 66      * 
 67      * @param savedInstanceState
 68      */
 69     @Override
 70     protected void onCreate(Bundle savedInstanceState)
 71     {
 72         // TODO Auto-generated method stub
 73         super.onCreate(savedInstanceState);
 74         setContentView(R.layout.my_runnable_main);
 75         init();
 76     }
 77  
 78     public void init()
 79     {
 80         pb = (ProgressBar)findViewById(R.id.progressBar1);
 81         findViewById(R.id.button1).setOnClickListener(this);
 82         findViewById(R.id.button2).setOnClickListener(this);
 83         findViewById(R.id.button3).setOnClickListener(this);
 84         findViewById(R.id.button4).setOnClickListener(this);
 85         findViewById(R.id.button5).setOnClickListener(this);
 86         taskQueue = new ConcurrentLinkedQueue<MyRunnable>();
 87         taskMap = new ConcurrentHashMap<Future, MyRunnable>();
 88         if (mES == null)
 89         {
 90             mES = Executors.newCachedThreadPool();
 91         }
 92  
 93         // 用于更新ProgressBar进度条
 94         mHandler = new Handler()
 95         {
 96             /**
 97              * Overriding methods
 98              * 
 99              * @param msg
100              */
101             @Override
102             public void handleMessage(Message msg)
103             {
104                 super.handleMessage(msg);
105                 pb.setProgress(msg.what);
106             }
107  
108         };
109  
110     }
111  
112     /**
113      * Overriding methods
114      * 
115      * @param v
116      */
117     @Override
118     public void onClick(View v)
119     {
120         switch (v.getId())
121         {
122             case R.id.button1:
123                 start();
124                 break;
125             case R.id.button2:
126                 stop();
127                 break;
128             case R.id.button3:
129                 reload(new MyRunnable(mHandler));
130                 break;
131             case R.id.button4:
132                 release();
133                 break;
134             case R.id.button5:
135                 addTask(new MyRunnable(mHandler));
136                 break;
137  
138             default:
139                 break;
140         }
141     }
142  
143     /**
144      * <Summary Description>
145      */
146     private void addTask(final MyRunnable mr)
147     {
148  
149         mHandler.sendEmptyMessage(0);
150  
151         if (mES == null)
152         {
153             mES = Executors.newCachedThreadPool();
154             notifyWork();
155         }
156  
157         if (taskQueue == null)
158         {
159             taskQueue = new ConcurrentLinkedQueue<MyRunnable>();
160         }
161  
162         if (taskMap == null)
163         {
164             taskMap = new ConcurrentHashMap<Future, MyRunnable>();
165         }
166  
167         mES.execute(new Runnable()
168         {
169  
170             @Override
171             public void run()
172             {
173                 /**
174                  * 插入一个Runnable到任务队列中 这个地方解释一下,offer跟add方法,试了下,效果都一样,没区别,官方的解释如下: 1 offer : Inserts the specified
175                  * element at the tail of this queue. As the queue is unbounded, this method will never return
176                  * {@code false}. 2 add: Inserts the specified element at the tail of this queue. As the queue is
177                  * unbounded, this method will never throw {@link IllegalStateException} or return {@code false}.
178                  * 
179                  * 
180                  * */
181                 taskQueue.offer(mr);
182                 // taskQueue.add(mr);
183                 notifyWork();
184             }
185         });
186  
187         Toast.makeText(MyRunnableActivity.this, "已添加一个新任务到线程池中 !", 0).show();
188     }
189  
190     /**
191      * <Summary Description>
192      */
193     private void release()
194     {
195         Toast.makeText(MyRunnableActivity.this, "释放所有占用的资源!", 0).show();
196  
197         /** 将ProgressBar进度置为0 */
198         mHandler.sendEmptyMessage(0);
199         isRuning = false;
200  
201         Iterator iter = taskMap.entrySet().iterator();
202         while (iter.hasNext())
203         {
204             Map.Entry<Future, MyRunnable> entry = (Map.Entry<Future, MyRunnable>)iter.next();
205             Future result = entry.getKey();
206             if (result == null)
207             {
208                 continue;
209             }
210             result.cancel(true);
211             taskMap.remove(result);
212         }
213         if (null != mES)
214         {
215             mES.shutdown();
216         }
217  
218         mES = null;
219         taskMap = null;
220         taskQueue = null;
221  
222     }
223  
224     /**
225      * <Summary Description>
226      */
227     private void reload(final MyRunnable mr)
228     {
229         mHandler.sendEmptyMessage(0);
230         if (mES == null)
231         {
232             mES = Executors.newCachedThreadPool();
233             notifyWork();
234         }
235  
236         if (taskQueue == null)
237         {
238             taskQueue = new ConcurrentLinkedQueue<MyRunnable>();
239         }
240  
241         if (taskMap == null)
242         {
243             taskMap = new ConcurrentHashMap<Future, MyRunnable>();
244         }
245  
246         mES.execute(new Runnable()
247         {
248  
249             @Override
250             public void run()
251             {
252                 /** 插入一个Runnable到任务队列中 */
253                 taskQueue.offer(mr);
254                 // taskQueue.add(mr);
255                 notifyWork();
256             }
257         });
258  
259         mES.execute(new Runnable()
260         {
261             @Override
262             public void run()
263             {
264                 if (isRuning)
265                 {
266                     MyRunnable myRunnable = null;
267                     synchronized (lock)
268                     {
269                         myRunnable = taskQueue.poll(); // 从线程队列中取出一个Runnable对象来执行,如果此队列为空,则调用poll()方法会返回null
270                         if (myRunnable == null)
271                         {
272                             isNotify = true;
273                         }
274                     }
275  
276                     if (myRunnable != null)
277                     {
278                         taskMap.put(mES.submit(myRunnable), myRunnable);
279                     }
280                 }
281             }
282         });
283     }
284  
285     /**
286      * <Summary Description>
287      */
288     private void stop()
289     {
290  
291         Toast.makeText(MyRunnableActivity.this, "任务已被取消!", 0).show();
292  
293         for (MyRunnable runnable : taskMap.values())
294         {
295             runnable.setCancleTaskUnit(true);
296         }
297     }
298  
299     /**
300      * <Summary Description>
301      */
302     private void start()
303     {
304  
305         if (mES == null || taskQueue == null || taskMap == null)
306         {
307             Log.i("KKK", "某资源是不是已经被释放了?");
308             return;
309         }
310         mES.execute(new Runnable()
311         {
312             @Override
313             public void run()
314             {
315                 if (isRuning)
316                 {
317                     MyRunnable myRunnable = null;
318                     synchronized (lock)
319                     {
320                         myRunnable = taskQueue.poll(); // 从线程队列中取出一个Runnable对象来执行,如果此队列为空,则调用poll()方法会返回null
321                         if (myRunnable == null)
322                         {
323                             isNotify = true;
324                             // try
325                             // {
326                             // myRunnable.wait(500);
327                             // }
328                             // catch (InterruptedException e)
329                             // {
330                             // e.printStackTrace();
331                             // }
332                         }
333                     }
334  
335                     if (myRunnable != null)
336                     {
337                         taskMap.put(mES.submit(myRunnable), myRunnable);
338                     }
339                 }
340  
341             }
342         });
343     }
344  
345     private void notifyWork()
346     {
347         synchronized (lock)
348         {
349             if (isNotify)
350             {
351                 lock.notifyAll();
352                 isNotify = !isNotify;
353             }
354         }
355     }
356 }

 

  2.2:辅助类(MyRunnable.java)

  1 package com.xiaoma.threadpooltest;
  2  
  3 import android.os.Handler;
  4 import android.os.SystemClock;
  5 import android.util.Log;
  6  
  7 /**
  8  * @TODO [The Class File Description]
  9  * @author XiaoMaGuo ^_^
 10  * @version [version-code, 2013-10-21]
 11  * @since [Product/module]
 12  */
 13 public class MyRunnable implements Runnable
 14 {
 15  
 16     private boolean cancleTask = false;
 17  
 18     private boolean cancleException = false;
 19  
 20     private Handler mHandler = null;
 21  
 22     public MyRunnable(Handler handler)
 23     {
 24         mHandler = handler;
 25     }
 26  
 27     /**
 28      * Overriding methods
 29      */
 30     @Override
 31     public void run()
 32     {
 33         Log.i("KKK", "MyRunnable  run() is executed!!! ");
 34         runBefore();
 35         if (cancleTask == false)
 36         {
 37             running();
 38             Log.i("KKK", "调用MyRunnable run()方法");
 39         }
 40  
 41         runAfter();
 42     }
 43  
 44     /**
 45      * <Summary Description>
 46      */
 47     private void runAfter()
 48     {
 49         Log.i("KKK", "runAfter()");
 50     }
 51  
 52     /**
 53      * <Summary Description>
 54      */
 55     private void running()
 56     {
 57         Log.i("KKK", "running()");
 58         try
 59         {
 60             // 做点有可能会出异常的事情!!!
 61             int prog = 0;
 62             if (cancleTask == false && cancleException == false)
 63             {
 64                 while (prog < 101)
 65                 {
 66                     if ((prog > 0 || prog == 0) && prog < 70)
 67                     {
 68                         SystemClock.sleep(100);
 69                     }
 70                     else
 71                     {
 72                         SystemClock.sleep(300);
 73                     }
 74                     if (cancleTask == false)
 75                     {
 76                         mHandler.sendEmptyMessage(prog++);
 77                         Log.i("KKK", "调用 prog++ = " + (prog));
 78                     }
 79                 }
 80             }
 81         }
 82         catch (Exception e)
 83         {
 84             cancleException = true;
 85         }
 86     }
 87  
 88     /**
 89      * <Summary Description>
 90      */
 91     private void runBefore()
 92     {
 93         // TODO Auto-generated method stub
 94         Log.i("KKK", "runBefore()");
 95     }
 96  
 97     public void setCancleTaskUnit(boolean cancleTask)
 98     {
 99         this.cancleTask = cancleTask;
100         Log.i("KKK", "点击了取消任务按钮 !!!");
101         // mHandler.sendEmptyMessage(0);
102     }
103  
104 }

 

  2.3:布局文件

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:orientation="vertical" >
 6  
 7     <LinearLayout
 8         android:layout_width="match_parent"
 9         android:layout_height="wrap_content"
10         android:orientation="horizontal" >
11  
12         <Button
13             android:id="@+id/button5"
14             android:layout_width="0dp"
15             android:layout_height="wrap_content"
16             android:layout_weight="1"
17             android:text="添加任务" />
18  
19         <Button
20             android:id="@+id/button1"
21             android:layout_width="0dp"
22             android:layout_height="wrap_content"
23             android:layout_weight="1"
24             android:text="开始任务" />
25  
26         <Button
27             android:id="@+id/button2"
28             android:layout_width="0dp"
29             android:layout_height="wrap_content"
30             android:layout_weight="1"
31             android:text="取消任务" />
32  
33         <Button
34             android:id="@+id/button3"
35             android:layout_width="0dp"
36             android:layout_height="wrap_content"
37             android:layout_weight="1"
38             android:text="重新加载" />
39  
40         <Button
41             android:id="@+id/button4"
42             android:layout_width="0dp"
43             android:layout_height="wrap_content"
44             android:layout_weight="1"
45             android:text="释放资源" />
46     </LinearLayout>
47  
48     <include layout="@layout/my_runnable_merge"/>
49  
50 </LinearLayout>

 

  方式一、方式二的全局配置文件AndroidManifest.xml文件的配置如下:

 1 <?xml version="1.0" encoding="utf-8"?>
 2 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
 3     package="com.xiaoma.threadpooltest"
 4     android:versionCode="1"
 5     android:versionName="1.0" >
 6  
 7     <uses-sdk
 8         android:minSdkVersion="8"
 9         android:targetSdkVersion="15" />
10  
11     <application
12         android:allowBackup="true"
13         android:icon="@drawable/ic_launcher"
14         android:label="@string/app_name"
15         android:theme="@style/AppTheme" >
16         <activity
17             android:name="Main"
18             android:label="@string/app_name" >
19 <!--             <intent-filter> -->
20 <!--                 <action android:name="android.intent.action.MAIN" /> -->
21  
22 <!--                 <category android:name="android.intent.category.LAUNCHER" /> -->
23 <!--             </intent-filter> -->
24         </activity>
25         <activity
26             android:name="MyRunnableActivity"
27             android:label="@string/app_name" >
28             <intent-filter>
29                 <action android:name="android.intent.action.MAIN" />
30  
31                 <category android:name="android.intent.category.LAUNCHER" />
32             </intent-filter>
33         </activity>
34     </application>
35  
36 </manifest>

 

  如果能仔细的将上面的东西都看完并消化的话,线程池方面的东西可能以后并不会太过为难你了!当然了,这些代码中写的都是一些比较简单的写法, 仅仅是使用了在线程中休眠的方式来模拟网络下载(还是个假象),如果在实际代码中使用时,尤其在释放资源这一块,不要只是单单释放了我们自己控制的线程池及其任务,还要将网络请求的Http也一同销毁(disconnection)掉,这样才算做到了完美!

posted @ 2015-01-10 21:11  supersheep6  阅读(259)  评论(0)    收藏  举报