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