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

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

  比如:线程名字、是否为用户线程等等属性

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

Android应用开发教程之二十九(终结篇):线程池的经典使用

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

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

  1.1:主类文件(Main.java)

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

  1.2:布局文件

XML/HTML代码
  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)

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

  2.2:辅助类(MyRunnable.java)

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

  2.3:布局文件

XML/HTML代码
  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文件的配置如下:

XML/HTML代码
  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://mzh3344258.blog.51cto.com/1823534/1313611 里面的附件下载,WordPress里面不知道怎么上传,大家多见谅吧,还得绕个路去下载,非常抱歉! O_O 如果能仔细的将上面的东西都看完并消化的话,线程池方面的东西可能以后并不会太过为难你啦!呵呵,当然了,这些代码中写的都是一些比较简单的写法, 仅仅是使用了在线程中休眠的方式来模拟网络下载(还是个假象),如果在实际代码中使用时,尤其在释放资源这一块,不要只是单单释放了我们自己控制的线程池及其任务,还要将网络请求的Http也一同销毁(disconnection)掉哦,这样才算做到了完美!如果还有哪位朋友没有安卓源码的话,可以到这个地址查看官方在线的安卓系统源码:https://github.com/android  急急忙忙写的,如果文章中有什么地方写的不对的,真的很希望Android老鸟、菜鸟都来指点、提问,代码中若不对的,或不太合理的地方,有朋友发觉了还请及时批评指正!先在此谢谢大家啦!加油,每天进步一点,坚持总会有收获的!废话不多说了,大家晚安!…O_O…

本文发布:Android开发网
本文地址:http://www.jizhuomi.com/android/course/656.html
2017年3月3日
发布:鸡啄米 分类:Android开发教程 浏览: 评论:0