线程池、线程的高效率使用,灵活控制!这里用最常用的几种方式来分别实现应用中使用的线程方面的知识,(共写了两个不同入口的Activity来分开不同的实现方式,大家可以自行注释AndroidManifest.xml中的Launch入口或打开注释)好了,先随便列几个吧,如:AsyncTask 、Runnable 、Thread、ThreadPool、 Executors等等的使用
一:无大小限制的线程池执行效果如下
二:限制按顺序来执行任务的线程池效果如下
三:一个一个任务的执行线程池效果如下(与按顺序执行效果是一样的,只是内部实现稍有不同)
四:按指定个数来执行任务的线程池效果如下
五:创建一个可在指定时间里执行任务的线程池,亦可重复执行,不常用,效果与四相同
六:按指定工厂模式来执行的线程池,效果与四、五一样,但用方式六创建的线程池都有在工厂中指定的线程属性,
比如:线程名字、是否为用户线程等等属性
七:线程池中任务执行时可暂停效果图如下
八:用Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现的效果图如下
(备注:为了写文章加注释还有查找的时候方便,把所有的主类及辅助类以内部类的形式写到一个.java文件里面了,如果朋友们觉得看着乱,不爽的话,可以自行将里面的类抽取到单独的.java文件中,几分钟搞定的事!)
方式一(纯ExecutorService、AsyncTask、Runnable关联实现相关文件如下):
1.1:主类文件(Main.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | package com.xxxx.threadpooltest; import java.util.ArrayList; import java.util.List; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import android.annotation.TargetApi; import android.app.Activity; import android.content.Context; import android.os.AsyncTask; import android.os.Build; import android.os.Bundle; import android.os.SystemClock; import android.util.AttributeSet; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.BaseAdapter; import android.widget.LinearLayout; import android.widget.ListView; import android.widget.ProgressBar; import android.widget.TextView; import android.widget.Toast; @TargetApi(Build.VERSION_CODES.HONEYCOMB) public class Main extends Activity { private static int order = 0; // private static final int count = Runtime.getRuntime().availableProcessors() * 3 + 2; private static final int count = 10; private static ExecutorService singleTaskExecutor = null; private static ExecutorService limitedTaskExecutor = null; private static ExecutorService allTaskExecutor = null; private static ExecutorService scheduledTaskExecutor = null; private static ExecutorService scheduledTaskFactoryExecutor = null; private List<AsyncTaskTest> mTaskList = null; private boolean isCancled = false; private boolean isClick = false; ThreadFactory tf = Executors.defaultThreadFactory(); private static class ThreadFactoryTest implements ThreadFactory { @Override public Thread newThread(Runnable r) { Thread thread = new Thread(r); thread.setName("xxxxx_ThreadFactory"); thread.setDaemon(true); // 将用户线程变成守护线程,默认false return thread; } } static { singleTaskExecutor = Executors.newSingleThreadExecutor();// 每次只执行一个线程任务的线程池 limitedTaskExecutor = Executors.newFixedThreadPool(3);// 限制线程池大小为7的线程池 allTaskExecutor = Executors.newCachedThreadPool(); // 一个没有限制最大线程数的线程池 scheduledTaskExecutor = Executors.newScheduledThreadPool(3);// 一个可以按指定时间可周期性的执行的线程池 scheduledTaskFactoryExecutor = Executors.newFixedThreadPool(3, new ThreadFactoryTest());// 按指定工厂模式来执行的线程池 scheduledTaskFactoryExecutor.submit(new Runnable() { @Override public void run() { Log.i("KKK", "This is the ThreadFactory Test submit Run! ! ! "); } }); }; @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.demo); final ListView taskList = (ListView)findViewById(R.id.task_list); taskList.setAdapter(new AsyncTaskAdapter(getApplication(), count)); taskList.setOnItemClickListener(new OnItemClickListener() { @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position == 0) // 以第一项为例,来测试关闭线程池 { // allTaskExecutor.shutdown(); List<Runnable> unExecRunn = allTaskExecutor.shutdownNow(); for (Runnable r : unExecRunn) { Log.i("KKK", "未执行的任务信息:=" + unExecRunn.toString()); } Log.i("KKK", "Is shutdown ? = " + String.valueOf(allTaskExecutor.isShutdown())); allTaskExecutor = null; } // 以第二项为例来测试是否取消执行的任务 AsyncTaskTest sat = mTaskList.get(1); if (position == 1) { if (!isClick) { sat.cancel(true); isCancled = true; isClick = !isClick; } else { sat.cancel(false); isCancled = false; // isClick = false; isClick = !isClick; if (null != sat && sat.getStatus() == AsyncTask.Status.RUNNING) { if (sat.isCancelled()) { sat = new AsyncTaskTest(sat.mTaskItem); } else { Toast.makeText(Main.this, "A task is already running, try later", Toast.LENGTH_SHORT).show(); } } if (allTaskExecutor == null) { allTaskExecutor = Executors.newCachedThreadPool(); } sat.executeOnExecutor(allTaskExecutor); // The task is already running(这也是个异常哦,小心使用! ) } } else { sat.cancel(false); isCancled = false; // sat.execute(sat.mTaskItem); // sat.executeOnExecutor(allTaskExecutor); } } }); } private class AsyncTaskAdapter extends BaseAdapter { private Context mContext; private LayoutInflater mFactory; private int mTaskCount; public AsyncTaskAdapter(Context context, int taskCount) { mContext = context; mFactory = LayoutInflater.from(mContext); mTaskCount = taskCount; mTaskList = new ArrayList<AsyncTaskTest>(taskCount); } @Override public int getCount() { return mTaskCount; } @Override public Object getItem(int position) { return mTaskList.get(position); } @Override public long getItemId(int position) { return position; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (convertView == null) { convertView = mFactory.inflate(R.layout.list_view_item, null); AsyncTaskTest task = new AsyncTaskTest((MyListItem)convertView); // task.execute(); // task.executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); // use AsyncTask#THREAD_POOL_EXECUTOR is the same to older version #execute() (less than API 11) // but different from newer version of #execute() // task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); // task.executeOnExecutor(singleTaskExecutor); // task.executeOnExecutor(limitedTaskExecutor); task.executeOnExecutor(allTaskExecutor); // task.executeOnExecutor(scheduledTaskExecutor); // task.executeOnExecutor(scheduledTaskFactoryExecutor); mTaskList.add(task); } return convertView; } } class AsyncTaskTest extends AsyncTask<Void, Integer, Void> { private MyListItem mTaskItem; private String id; private AsyncTaskTest(MyListItem item) { mTaskItem = item; if (order < count || order == count) { id = "执行:" + String.valueOf(++order); } else { order = 0; id = "执行:" + String.valueOf(++order); } } @Override protected void onPreExecute() { mTaskItem.setTitle(id); } @Override protected void onCancelled() { super.onCancelled(); } @Override protected Void doInBackground(Void... params) { if (!isCancelled() && isCancled == false) // 这个地方很关键,如果不设置标志位的话,直接setCancel(true)是无效的 { int prog = 0; while (prog < 101) { if ((prog > 0 || prog == 0) && prog < 70) // 小于70%时,加快进度条更新 { SystemClock.sleep(100); } else // 大于70%时,减慢进度条更新 { SystemClock.sleep(300); } publishProgress(prog); // 更新进度条 prog++; } } return null; } @Override protected void onPostExecute(Void result) { } @Override protected void onProgressUpdate(Integer... values) { mTaskItem.setProgress(values[0]); // 设置进度 } } } class MyListItem extends LinearLayout { private TextView mTitle; private ProgressBar mProgress; public MyListItem(Context context, AttributeSet attrs) { super(context, attrs); } public MyListItem(Context context) { super(context); } public void setTitle(String title) { if (mTitle == null) { mTitle = (TextView)findViewById(R.id.task_name); } mTitle.setText(title); } public void setProgress(int prog) { if (mProgress == null) { mProgress = (ProgressBar)findViewById(R.id.task_progress); } mProgress.setProgress(prog); } } |
1.2:布局文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="10dip" android:paddingRight="10dip" android:orientation="vertical" > <ListView android:id="@+id/task_list" android:layout_width="fill_parent" android:layout_height="wrap_content" android:divider="#cccccc" android:dividerHeight="0.6dip" android:footerDividersEnabled="true" android:headerDividersEnabled="true" /> </LinearLayout> |
方式二(Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService关联实现的相关文件如 下):
2.1:主类文件(MyRunnableActivity.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 | package com.xxxxx.threadpooltest; import java.util.Iterator; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.os.Message; import android.util.Log; import android.view.View; import android.view.View.OnClickListener; import android.widget.ProgressBar; import android.widget.Toast; public class MyRunnableActivity extends Activity implements OnClickListener { private ConcurrentLinkedQueue<MyRunnable> taskQueue = null; private ConcurrentMap<Future, MyRunnable> taskMap = null; private ExecutorService mES = null; private Object lock = new Object(); private boolean isNotify = true; private boolean isRuning = true; private ProgressBar pb = null; private Handler mHandler = null; @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); setContentView(R.layout.my_runnable_main); init(); } public void init() { pb = (ProgressBar)findViewById(R.id.progressBar1); findViewById(R.id.button1).setOnClickListener(this); findViewById(R.id.button2).setOnClickListener(this); findViewById(R.id.button3).setOnClickListener(this); findViewById(R.id.button4).setOnClickListener(this); findViewById(R.id.button5).setOnClickListener(this); taskQueue = new ConcurrentLinkedQueue<MyRunnable>(); taskMap = new ConcurrentHashMap<Future, MyRunnable>(); if (mES == null) { mES = Executors.newCachedThreadPool(); } // 用于更新ProgressBar进度条 mHandler = new Handler() { @Override public void handleMessage(Message msg) { super.handleMessage(msg); pb.setProgress(msg.what); } }; } @Override public void onClick(View v) { switch (v.getId()) { case R.id.button1: start(); break; case R.id.button2: stop(); break; case R.id.button3: reload(new MyRunnable(mHandler)); break; case R.id.button4: release(); break; case R.id.button5: addTask(new MyRunnable(mHandler)); break; default: break; } } private void addTask(final MyRunnable mr) { mHandler.sendEmptyMessage(0); if (mES == null) { mES = Executors.newCachedThreadPool(); notifyWork(); } if (taskQueue == null) { taskQueue = new ConcurrentLinkedQueue<MyRunnable>(); } if (taskMap == null) { taskMap = new ConcurrentHashMap<Future, MyRunnable>(); } mES.execute(new Runnable() { @Override public void run() { taskQueue.offer(mr); // taskQueue.add(mr); notifyWork(); } }); Toast.makeText(MyRunnableActivity.this, "已添加一个新任务到线程池中 !", 0).show(); } private void release() { Toast.makeText(MyRunnableActivity.this, "释放所有占用的资源!", 0).show(); mHandler.sendEmptyMessage(0); isRuning = false; Iterator iter = taskMap.entrySet().iterator(); while (iter.hasNext()) { Map.Entry<Future, MyRunnable> entry = (Map.Entry<Future, MyRunnable>)iter.next(); Future result = entry.getKey(); if (result == null) { continue; } result.cancel(true); taskMap.remove(result); } if (null != mES) { mES.shutdown(); } mES = null; taskMap = null; taskQueue = null; } private void reload(final MyRunnable mr) { mHandler.sendEmptyMessage(0); if (mES == null) { mES = Executors.newCachedThreadPool(); notifyWork(); } if (taskQueue == null) { taskQueue = new ConcurrentLinkedQueue<MyRunnable>(); } if (taskMap == null) { taskMap = new ConcurrentHashMap<Future, MyRunnable>(); } mES.execute(new Runnable() { @Override public void run() { taskQueue.offer(mr); // taskQueue.add(mr); notifyWork(); } }); mES.execute(new Runnable() { @Override public void run() { if (isRuning) { MyRunnable myRunnable = null; synchronized (lock) { myRunnable = taskQueue.poll(); // 从线程队列中取出一个Runnable对象来执行,如果此队列为空,则调用poll()方法会返回null if (myRunnable == null) { isNotify = true; } } if (myRunnable != null) { taskMap.put(mES.submit(myRunnable), myRunnable); } } } }); } private void stop() { Toast.makeText(MyRunnableActivity.this, "任务已被取消!", 0).show(); for (MyRunnable runnable : taskMap.values()) { runnable.setCancleTaskUnit(true); } } private void start() { if (mES == null || taskQueue == null || taskMap == null) { Log.i("KKK", "某资源是不是已经被释放了?"); return; } mES.execute(new Runnable() { @Override public void run() { if (isRuning) { MyRunnable myRunnable = null; synchronized (lock) { // 从线程队列中取出一个Runnable对象来执行,如果此队列为空,则调用poll()方法会返回null myRunnable = taskQueue.poll(); if (myRunnable == null) { isNotify = true; // try // { // myRunnable.wait(500); // } // catch (InterruptedException e) // { // e.printStackTrace(); // } } } if (myRunnable != null) { taskMap.put(mES.submit(myRunnable), myRunnable); } } } }); } private void notifyWork() { synchronized (lock) { if (isNotify) { lock.notifyAll(); isNotify = !isNotify; } } } } |
2.2:辅助类(MyRunnable.java)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | package com.xxxxx.threadpooltest; import android.os.Handler; import android.os.SystemClock; import android.util.Log; public class MyRunnable implements Runnable { private boolean cancleTask = false; private boolean cancleException = false; private Handler mHandler = null; public MyRunnable(Handler handler) { mHandler = handler; } @Override public void run() { Log.i("KKK", "MyRunnable run() is executed!!! "); runBefore(); if (cancleTask == false) { running(); Log.i("KKK", "调用MyRunnable run()方法"); } runAfter(); } private void runAfter() { Log.i("KKK", "runAfter()"); } private void running() { Log.i("KKK", "running()"); try { // 做点有可能会出异常的事情!!! int prog = 0; if (cancleTask == false && cancleException == false) { while (prog < 101) { if ((prog > 0 || prog == 0) && prog < 70) { SystemClock.sleep(100); } else { SystemClock.sleep(300); } if (cancleTask == false) { mHandler.sendEmptyMessage(prog++); Log.i("KKK", "调用 prog++ = " + (prog)); } } } } catch (Exception e) { cancleException = true; } } private void runBefore() { // TODO Auto-generated method stub Log.i("KKK", "runBefore()"); } public void setCancleTaskUnit(boolean cancleTask) { this.cancleTask = cancleTask; Log.i("KKK", "点击了取消任务按钮 !!!"); // mHandler.sendEmptyMessage(0); } } |
2.3:布局文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <Button android:id="@+id/button5" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="添加任务" /> <Button android:id="@+id/button1" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="开始任务" /> <Button android:id="@+id/button2" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消任务" /> <Button android:id="@+id/button3" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="重新加载" /> <Button android:id="@+id/button4" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="释放资源" /> </LinearLayout> <include layout="@layout/my_runnable_merge"/> </LinearLayout> |
方式一、方式二的全局配置文件AndroidManifest.xml文件的配置如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.xxxx.threadpooltest" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="Main" android:label="@string/app_name" > <!-- <intent-filter> --> <!-- <action android:name="android.intent.action.MAIN" /> --> <!-- <category android:name="android.intent.category.LAUNCHER" /> --> <!-- </intent-filter> --> </activity> <activity android:name="MyRunnableActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
源码:http://mzh3344258.blog.51cto.com/1823534/1313611 里面的附件,WordPress里面不知道怎么上传,大家多见谅吧.
这些代码中写的都是一些比较简单的写法, 仅仅是使用了在线程中休眠的方式来模拟网络下载(还是个假象),如果在实际代码中使用时,尤其在释放资源这一块,不要只是单单释放了我们自己控制的线程池及其任务,还要将网络请求的Http也一同销毁(disconnection)掉哦,这样才算做到了完美!
如果还有哪位朋友没有安卓源码的话,可以到这个地址查看官方在线的安卓系统源码:https://github.com/android
- 本文固定链接: https://www.xuanyusong.com/archives/2439