Android线程池AsyncTask使用
由于经常会在网上或群里看到有朋友会问线程方面的东西,就像我一个朋友他们老师讲的,J2SE、J2EE里面使用的线程方面的东西可能不是太多 ,但是在Android开发里面,玩的就是线程(UI Thread)! 好了,废话就说这么多吧,直入正题!今天要讲的东西就是线程池、线程的高效率使用,灵活控制!今天死马我就用最常用的几种方式来分别实现应用中使用的线程方面的知识,(共写了两个不同入口的Activity来分开不同的实现方式,大家可以自行注释AndroidManifest.xml中的Launch入口或打开注释)好了,先随便列几个吧,如:AsyncTask 、Runnable 、Thread、ThreadPool、 Executors等等的使用,先上效果,再一步步分解代码,来吧,效果图如下:
一:无大小限制的线程池执行效果如下
二:限制按顺序来执行任务的线程池效果如下
三:一个一个任务的执行线程池效果如下(与按顺序执行效果是一样的,只是内部实现稍有不同)
四:按指定个数来执行任务的线程池效果如下
五:创建一个可在指定时间里执行任务的线程池,亦可重复执行,不常用,效果与四相同
六:按指定工厂模式来执行的线程池,效果与四、五一样,但用方式六创建的线程池都有在工厂中指定的线程属性,比如:线程名字、是否为用户线程等等属性
七:线程池中任务执行时可暂停效果图如下
八:用Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现的效果图如下
哦了,效果看完了,现在就请大家自行修改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>









浙公网安备 33010602011771号