Android開發(fā)經(jīng)驗談:并發(fā)編程(線程與線程池)(推薦)
一、線程
在Android開發(fā)中,你不可能都在主線程中開發(fā),畢竟要聯(lián)網(wǎng),下載數(shù)據(jù),保存數(shù)據(jù)等操作,當(dāng)然這就離不開線程。
(當(dāng)然你可以在Android4.0以前的手機(jī)里在主線程請求網(wǎng)絡(luò),我最早開發(fā)的時候,用的手機(jī)比較古老。。。)
在Android中你可以隨意創(chuàng)建線程,于是就會造成線程不可控,內(nèi)存泄漏,創(chuàng)建線程消耗資源,線程太多了消耗資源等問題。
具體線程怎么創(chuàng)建我就不在文章里描述了,畢竟這主要將并發(fā)編程。。。。
大家知道線程不可控就好了。。。于是就需要對線程進(jìn)行控制,防止一系列問題出現(xiàn),這就用到了如下要講的東西。
二、線程池
線程池:顧名思義,就是放線程的大池子。
如何創(chuàng)建一個線程池?
先說說幾個系統(tǒng)的線程池:
- FixedThreadPool 創(chuàng)建定長線程的線程池
- CachedThreadPool 需要的時候建立新的線程,超時線程銷毀
- SingleThreadPool 單個線程的線程池
- ScheduledThreadPool 可以定時的線程池,創(chuàng)建周期性的任務(wù)
這幾個線程池不做多余闡述,因為這些線程池的原理都與我下面要講的有關(guān)。。。。
如何自定義線程池(先來了解幾個必須知道的參數(shù)):
corePoolSize:
核心線程池大小,線程池中主要工作的線程的多少。
maximumPoolSize:
線程池最大線程數(shù)。
keepAliveTime:
空閑線程可保持的時間是多久,如果你啟用了allowCoreThreadTimeOut方法,你的線程池里的空閑線程在這個時間段后會自動銷毀,如果沒啟用,則只要不超過corePoolSize,空閑線程也不會銷毀。
Unit:
keepAliveTime的時間單位
workQueue:
阻塞隊列,當(dāng)任務(wù)達(dá)到corePoolSize,就會被放入這個隊列
常見幾種BlockingQueue實現(xiàn)
- ArrayBlockingQueue : 有界的數(shù)組隊列
- LinkedBlockingQueue : 可支持有界/無界的隊列,使用鏈表實現(xiàn)
- PriorityBlockingQueue : 優(yōu)先隊列,可以針對任務(wù)排序
- SynchronousQueue : 隊列長度為1的隊列,和Array有點區(qū)別就是:client thread提交到block queue會是一個阻塞過程,直到有一個worker thread連接上來poll task。
threadFactory:
線程工廠,主要用來創(chuàng)建線程;
handler:
表示當(dāng)拒絕處理任務(wù)時的策略,也就是參數(shù)maximumPoolSize達(dá)到后丟棄處理的方法。有以下四種取值:
- ThreadPoolExecutor.AbortPolicy:丟棄任務(wù)并拋出RejectedExecutionException異常。
- ThreadPoolExecutor.DiscardPolicy:也是丟棄任務(wù),但是不拋出異常。
- ThreadPoolExecutor.DiscardOldestPolicy:丟棄隊列最前面的任務(wù),然后重新嘗試執(zhí)行任務(wù)(重復(fù)此過程)
- ThreadPoolExecutor.CallerRunsPolicy:由調(diào)用線程處理該任務(wù)
用戶也可以實現(xiàn)接口RejectedExecutionHandler定制自己的策略。
代碼展示:
//線程工廠
public class TaskThreadFactory implements ThreadFactory {
private final AtomicInteger mThreadNumber = new AtomicInteger(1);
private final String mNamePrefix;
TaskThreadFactory(String name) {
mNamePrefix = name + "#";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(r,mNamePrefix + mThreadNumber.getAndIncrement());
// if (t.isDaemon())
// t.setDaemon(false);
//
// if (t.getPriority() != Thread.NORM_PRIORITY)
// t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
//重寫runnable
public class PRunnable implements Runnable {
public static final int HIGH = 1;//優(yōu)先級高
public static final int NORMAL = 2;//優(yōu)先級中等
public static final int LOW = 3;//優(yōu)先級低
@IntDef({HIGH,NORMAL,LOW})
@Retention(RetentionPolicy.SOURCE)
public @interface Priority{}
public final int priority;
private final Runnable runnable;
public int serial;
public PRunnable(Runnable runnable){
this(NORMAL,runnable);
}
public PRunnable(@Priority int priority,Runnable runnable){
this.priority = priority;
this.runnable = runnable;
}
@Override
public void run() {
if (runnable != null) {
runnable.run();
}
}
/**
* 線程隊列方式 先進(jìn)先出
* @param r1
* @param r2
* @return
*/
public static final int compareFIFO(PRunnable r1, PRunnable r2) {
int result = r1.priority-r2.priority;
return result==0?r1.serial-r2.serial:result;
}
/**
* 線程隊列方式 后進(jìn)先出
* @param r1
* @param r2
* @return
*/
public static final int compareLIFO(PRunnable r1, PRunnable r2) {
int result = r1.priority-r2.priority;
return result==0?r2.serial-r1.serial:result;
}
}
//線程池實現(xiàn)
public class TaskExecutor implements Executor {
private final static int QUEUE_INIT_CAPACITY = 20;
private static final int CORE = 3;
private static final int MAX = 5;
private static final int TIMEOUT = 30 * 1000;
private AtomicInteger SERIAL = new AtomicInteger(0);//主要獲取添加任務(wù)
public static class Config {
public int core;
public int max;
public int timeout;
public boolean allowCoreTimeOut;
public boolean fifo;
public Config(int core, int max, int timeout, boolean allowCoreTimeOut,boolean fifo) {
this.core = core;
this.max = max;
this.timeout = timeout;
this.allowCoreTimeOut = allowCoreTimeOut;
this.fifo = fifo;
}
}
public static Config defaultConfig = new Config(CORE, MAX, TIMEOUT, true,true);
private final String name;
private final Config config;
private ExecutorService service;
public TaskExecutor(String name) {
this(name, defaultConfig);
}
public TaskExecutor(String name, Config config) {
this(name, config, true);
}
public TaskExecutor(String name, Config config, boolean startup) {
this.name = name;
this.config = config;
if (startup) {
startup();
}
}
public void startup() {
synchronized (this) {
if (service != null && !service.isShutdown()) {
return;
}
service = createExecutor(config);
}
}
public void shutdown() {
ExecutorService executor = null;
synchronized (this) {
// 交換變量
if (service != null) {
executor = service;
service = null;
}
}
if (executor != null) {
// 停止線程
if (!executor.isShutdown()) {
executor.shutdown();
}
// 回收變量
executor = null;
}
}
private void executeRunnable(PRunnable runnable) {
synchronized (this) {
if (service == null || service.isShutdown()) {
return;
}
runnable.serial = SERIAL.getAndIncrement();
service.execute(runnable);
}
}
@Override
public void execute(Runnable runnable) {
if (runnable instanceof PRunnable) {
executeRunnable((PRunnable) runnable);
}else{
executeRunnable(new PRunnable(runnable));
}
}
public Future<?> submit(Runnable runnable) {
synchronized (this) {
if (service == null || service.isShutdown()) {
return null;
}
if (runnable instanceof PRunnable) {
((PRunnable) runnable).serial = SERIAL.getAndIncrement();
return service.submit(runnable);
}else{
PRunnable pRunnable = new PRunnable(runnable);
pRunnable.serial = SERIAL.getAndIncrement();
return service.submit(pRunnable);
}
}
}
public void execute(Runnable runnable, @PRunnable.Priority int priority) {
executeRunnable(new PRunnable(priority,runnable));
}
private ExecutorService createExecutor(Config config) {
ThreadPoolExecutor service = new ThreadPoolExecutor(config.core, config.max, config.timeout,
TimeUnit.MILLISECONDS, new PriorityBlockingQueue<Runnable>(QUEUE_INIT_CAPACITY, config.fifo ? mQueueFIFOComparator : mQueueLIFOComparator),
new TaskThreadFactory(name), new ThreadPoolExecutor.DiscardPolicy());
allowCoreThreadTimeOut(service, config.allowCoreTimeOut);
return service;
}
public boolean isBusy() {
synchronized (this) {
if (service == null || service.isShutdown()) {
return false;
}
if(service instanceof ThreadPoolExecutor){
ThreadPoolExecutor tService = (ThreadPoolExecutor) service;
return tService.getActiveCount() >= tService.getCorePoolSize();
}
return false;
}
}
private static final void allowCoreThreadTimeOut(ThreadPoolExecutor service, boolean value) {
if (Build.VERSION.SDK_INT >= 9) {
allowCoreThreadTimeOut9(service, value);
}
}
@TargetApi(9)
private static final void allowCoreThreadTimeOut9(ThreadPoolExecutor service, boolean value) {
service.allowCoreThreadTimeOut(value);
}
Comparator<Runnable> mQueueFIFOComparator = new Comparator<Runnable>() {
@Override
public int compare(Runnable lhs, Runnable rhs) {
PRunnable r1 = (PRunnable) lhs;
PRunnable r2 = (PRunnable) rhs;
return PRunnable.compareFIFO(r1, r2);
}
};
Comparator<Runnable> mQueueLIFOComparator = new Comparator<Runnable>() {
@Override
public int compare(Runnable lhs, Runnable rhs) {
PRunnable r1 = (PRunnable) lhs;
PRunnable r2 = (PRunnable) rhs;
return PRunnable.compareLIFO(r1, r2);
}
};
}
以上所述是小編給大家介紹的Android開發(fā)經(jīng)驗談:并發(fā)編程(線程與線程池)詳解整合,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
Android studio 4.1打包失敗和插件錯誤提示的解決
這篇文章主要介紹了Android studio 4.1打包失敗和插件錯誤提示的解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Android?imageVIew實現(xiàn)鏡像旋轉(zhuǎn)的方法
在Android應(yīng)用開發(fā)中,有時候我們需要對ImageView中的圖片進(jìn)行鏡像旋轉(zhuǎn),以展示不同的效果,本文將介紹如何使用代碼實現(xiàn)ImageView的鏡像旋轉(zhuǎn)效果,這篇文章主要介紹了Android?imageVIew如何做鏡像旋轉(zhuǎn),需要的朋友可以參考下2024-06-06
Android Studio 3.0上分析內(nèi)存泄漏的原因
本篇文章主要介紹了Android Studio 3.0上分析內(nèi)存泄漏的原因,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11
android studio 的下拉菜單Spinner使用詳解
這篇文章主要介紹了android studio 的下拉菜單Spinner使用詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12
Android library native調(diào)試代碼遇到的問題解決
這篇文章主要介紹了Android library native 代碼不能調(diào)試解決方法匯總,android native開發(fā)會碰到native代碼無法調(diào)試問題,而app主工程中的native代碼是可以調(diào)試的2023-04-04
Android 網(wǎng)絡(luò)圖片查看器與網(wǎng)頁源碼查看器
本篇文章主要介紹了Android 網(wǎng)絡(luò)圖片查看器與網(wǎng)頁源碼查看器的相關(guān)知識。具有很好的參考價值。下面跟著小編一起來看下吧2017-04-04

