Android研究院之應用開發線程池的經典使用

轉載自:http://mzh3344258.blog.51cto.com/1823534/1313611


Android線程池使用終結版

有一段時間沒寫博文了,今天抽空總結一下,也希望能通過自己寫的這些文章,加深理解的同時能幫

助在技術方面有疑點的朋友搞清楚個所以然來,由於經常會在網上或羣裏看到有朋友會問線程方面的

東西,就像我一個朋友他們老師講的,J2SE、J2EE裏面使用的線程方面的東西可能不是太多,但是

在Android開發裏面,玩的就是線程(UIThread)!好了,廢話就說這麼多吧,直入正題!今天要講的

東西就是線程池、線程的高效率使用,靈活控制!今天死馬我就用最常用的幾種方式來分別實現應用

中使用的線程方面的知識,(共寫了兩個不同入口的Activity來分開不同的實現方式,大家可以自行注

釋AndroidManifest.xml中的Launch入口或打開註釋)任何發代碼中的具體實現效果,好了,先隨便列

幾個吧,如:AsyncTask、Runnable、Thread、ThreadPool、Executors等等的使用,看我文章的朋

友應該都很清楚小馬的方式啦,果斷先上效果,再一步步分解代碼,來吧,效果圖如下:

一:無大小限制的線程池執行效果如下

二:限制按順序來執行任務的線程池效果如下

222725754.gif

三:一個一個任務的執行線程池效果如下(與按順序執行效果是一樣的,只是內部實現稍有不同)

222657697.gif

四:按指定個數來執行任務的線程池效果如下

222840612.gif

五:創建一個可在指定時間裏執行任務的線程池,亦可重複執行,不常用,效果與四相同

222856182.gif

六:按指定工廠模式來執行的線程池,效果與四、五一樣,但用方式六創建的線程池都有在工廠

中指定的線程屬性,比如:線程名字、是否爲用戶線程等等屬性

222913795.gif

七:線程池中任務執行時可暫停效果圖如下

222933493.gif

八:用Runnable、ConcurrentLinkedQueue、ConcurrentMap、Future、ExecutorService關聯實現的效果圖如下

222950866.gif

哦的了,效果看完了,現在就請大家自行修改AndroidManifest.xml中主Activity的入口來看兩種不同方式實現的代碼效果吧,首先,先貼一下Main.java類的代碼,希望大家詳細看裏面的註釋,一定要詳細看,你不會吃虧的,相信我!(備註:爲了寫文章加註釋還有查找的時候方便,小馬把所有的主類及輔助類以內部類的形式寫到一個.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
/*
* FileName:  Main.java
* CopyRight:  Belong to  <XiaoMaGuo Technologies > own
* Description:  <description>
* Modify By :  XiaoMaGuo ^_^
* Modify Date:   2013-10-15
* Follow Order No.:  <Follow Order No.>
* Modify Order No.:  <Modify Order No.>
* Modify Content:  <modify content >
*/
package com.xiaoma.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;
/**
* @TODO [The Class File Description]
* @author XiaoMaGuo ^_^
* @version [version-code, 2013-10-15]
* @since [Product/module]
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class Main extends Activity
{
private static int order = 0;
/** 總共多少任務(根據CPU個數決定創建活動線程的個數,這樣取的好處就是可以讓手機承受得住) */
// private static final int count = Runtime.getRuntime().availableProcessors() * 3 + 2;
/** 總共多少任務(我是在模擬器裏面跑的,爲了效果明顯,所以寫死了爲10個,如果在手機上的話,推薦使用上面的那個count) */
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("XiaoMaGuo_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) // 以第一項爲例,來測試關閉線程池
{
/**
* 會關閉線程池方式一:但不接收新的Task,關閉後,正在等待 執行的任務不受任何影響,會正常執行,無返回值!
*/
// allTaskExecutor.shutdown();
/**
* 會關閉線程池方式二:也不接收新的Task,並停止正等待執行的Task(也就是說, 執行到一半的任務將正常執行下去),最終還會給你返回一個正在等待執行但線程池關閉卻沒有被執行的Task集合!
*/
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();
}
}
/**
* 由於上面測試關閉,在不重新生成allTaskExecutor的同時,會報異常(沒有可以使用的線程池,故此處重新生成線程池對象)
*/
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);
}
}
});
}
/**
* @TODO [ListView Item的條目適配器]
* @author XiaoMaGuo ^_^
* @version [version-code, 2013-10-22]
* @since [Product/module]
*/
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);
/**
* 下面的方式在小於API 11級時效果是一樣的,但在高版本中的稍微有點不同,可以看以下AsyncTask核心變量的定義就知道了使用如下
* 方式時,系統會默認的採用五個一組,五個一組的方式來執行我們的任務,定義在:AsyncTask.class中,private static final int CORE_POOL_SIZE = 5;
* */
// 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);
/**
* 一個一個執行我們的任務,效果與按順序執行是一樣的(AsyncTask.SERIAL_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);
}
/**
* Overriding methods
*/
@Override
protected void onCancelled()
{
super.onCancelled();
}
@Override
protected Void doInVoid...  params)
{
if (!isCancelled() && isCancled == false) // 這個地方很關鍵,如果不設置標誌位的話,直接setCancel(true)是無效的
{
int prog = 0;
/**
* 下面的while中,小馬寫了個分支用來做個假象(任務東西剛開始下載的時候,速度快,快下載完成的時候就突然間慢了下來的效果, 大家可以想象一下,類似
* :PP手機助手、91手機助手中或其它手機應用中,幾乎都有這個假象,開始快,結束時就下載變慢了,講白了 就是開發的人不想讓你在下載到大於一半的時候,也就是快下載完的時候去點取消,你那樣得多浪費
* !所以造個假象,讓你不想去取消而已)
*/
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]); // 設置進度
}
}
}
/**
* @TODO [一個簡單的自定義 ListView Item]
* @author XiaoMaGuo ^_^
* @version [version-code, 2013-10-22]
* @since [Product/module]
*/
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
/*
* FileName:  MyRunnableActivity.java
* CopyRight:  Belong to  <XiaoMaGuo Technologies > own
* Description:  <description>
* Modify By :  XiaoMaGuo ^_^
* Modify Date:   2013-10-21
* Follow Order No.:  <Follow Order No.>
* Modify Order No.:  <Modify Order No.>
* Modify Content:  <modify content >
*/
package com.xiaoma.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;
/**
* @TODO [線程池控制 ]
* @author XiaoMaGuo ^_^
* @version [version-code, 2013-10-22]
* @since [Product/module]
*/
public class MyRunnableActivity extends Activity implements OnClickListener
{
/** 任務執行隊列 */
private ConcurrentLinkedQueue<MyRunnable> taskQueue = null;
/**
* 正在等待執行或已經完成的任務隊列
*
* 備註:Future類,一個用於存儲異步任務執行的結果,比如:判斷是否取消、是否可以取消、是否正在執行、是否已經完成等
*
* */
private ConcurrentMap<Future, MyRunnable> taskMap = null;
/**
* 創建一個不限制大小的線程池 此類主要有以下好處 1,以共享的無界隊列方式來運行這些線程. 2,執行效率高。 3,在任意點,在大多數 nThreads 線程會處於處理任務的活動狀態
* 4,如果在關閉前的執行期間由於失敗而導致任何線程終止,那麼一個新線程將代替它執行後續的任務(如果需要)。
*
* */
private ExecutorService mES = null;
/** 在此類中使用同步鎖時使用如下lock對象即可,官方推薦的,不推薦直接使用MyRunnableActivity.this類型的,可以詳細讀一下/framework/app下面的隨便一個項目 */
private Object lock = new Object();
/** 喚醒標誌,是否喚醒線程池工作 */
private boolean isNotify = true;
/** 線程池是否處於運行狀態(即:是否被釋放!) */
private boolean isRuning = true;
/** 任務進度 */
private ProgressBar pb = null;
/** 用此Handler來更新我們的UI */
private Handler mHandler = null;
/**
* Overriding methods
*
* @param savedInstanceState
*/
@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()
{
/**
* Overriding methods
*
* @param msg
*/
@Override
public void handleMessage(Message msg)
{
super.handleMessage(msg);
pb.setProgress(msg.what);
}
};
}
/**
* Overriding methods
*
* @param v
*/
@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;
}
}
/**
* <Summary Description>
*/
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()
{
/**
* 插入一個Runnable到任務隊列中 這個地方解釋一下,offer跟add方法,試了下,效果都一樣,沒區別,官方的解釋如下: 1 offer : Inserts the specified
* element at the tail of this queue. As the queue is unbounded, this method will never return
* {@code false}. 2 add: Inserts the specified element at the tail of this queue. As the queue is
* unbounded, this method will never throw {@link IllegalStateException} or return {@code false}.
*
*
* */
taskQueue.offer(mr);
// taskQueue.add(mr);
notifyWork();
}
});
Toast.makeText(MyRunnableActivity.this, "已添加一個新任務到線程池中 !", 0).show();
}
/**
* <Summary Description>
*/
private void release()
{
Toast.makeText(MyRunnableActivity.this, "釋放所有佔用的資源!", 0).show();
/** 將ProgressBar進度置爲0 */
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;
}
/**
* <Summary Description>
*/
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()
{
/** 插入一個Runnable到任務隊列中 */
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);
}
}
}
});
}
/**
* <Summary Description>
*/
private void stop()
{
Toast.makeText(MyRunnableActivity.this, "任務已被取消!", 0).show();
for (MyRunnable runnable : taskMap.values())
{
runnable.setCancleTaskUnit(true);
}
}
/**
* <Summary Description>
*/
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)
{
myRunnable = taskQueue.poll(); // 從線程隊列中取出一個Runnable對象來執行,如果此隊列爲空,則調用poll()方法會返回null
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
/*
* FileName:  MyRunnable.java
* CopyRight:  Belong to  <XiaoMaGuo Technologies > own
* Description:  <description>
* Modify By :  XiaoMaGuo ^_^
* Modify Date:   2013-10-21
* Follow Order No.:  <Follow Order No.>
* Modify Order No.:  <Modify Order No.>
* Modify Content:  <modify content >
*/
package com.xiaoma.threadpooltest;
import android.os.Handler;
import android.os.SystemClock;
import android.util.Log;
/**
* @TODO [The Class File Description]
* @author XiaoMaGuo ^_^
* @version [version-code, 2013-10-21]
* @since [Product/module]
*/
public class MyRunnable implements Runnable
{
private boolean cancleTask = false;
private boolean cancleException = false;
private Handler mHandler = null;
public MyRunnable(Handler handler)
{
mHandler = handler;
}
/**
* Overriding methods
*/
@Override
public void run()
{
Log.i("KKK", "MyRunnable  run() is executed!!! ");
runBefore();
if (cancleTask == false)
{
running();
Log.i("KKK", "調用MyRunnable run()方法");
}
runAfter();
}
/**
* <Summary Description>
*/
private void runAfter()
{
Log.i("KKK", "runAfter()");
}
/**
* <Summary Description>
*/
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;
}
}
/**
* <Summary Description>
*/
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
<?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
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.xiaoma.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也一同銷燬掉哦,這樣纔算做到了完美!急急忙忙寫的,如果文章中有什麼地方寫的不對的,真的很希望Android老鳥、菜鳥都來指點、提問,代碼中若不對的,或不太合理的地方,有朋友發覺了還請及時批評指正!小馬先在此謝謝大家啦!加油,每天進步一點,堅持總會有收穫的!廢話不多說了,大家晚安!…O_O…


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章