Android中關(guān)于主線程的理解:
公司主營(yíng)業(yè)務(wù):網(wǎng)站建設(shè)、成都做網(wǎng)站、移動(dòng)網(wǎng)站開(kāi)發(fā)等業(yè)務(wù)。幫助企業(yè)客戶(hù)真正實(shí)現(xiàn)互聯(lián)網(wǎng)宣傳,提高企業(yè)的競(jìng)爭(zhēng)能力。創(chuàng)新互聯(lián)建站是一支青春激揚(yáng)、勤奮敬業(yè)、活力青春激揚(yáng)、勤奮敬業(yè)、活力澎湃、和諧高效的團(tuán)隊(duì)。公司秉承以“開(kāi)放、自由、嚴(yán)謹(jǐn)、自律”為核心的企業(yè)文化,感謝他們對(duì)我們的高要求,感謝他們從不同領(lǐng)域給我們帶來(lái)的挑戰(zhàn),讓我們激情的團(tuán)隊(duì)有機(jī)會(huì)用頭腦與智慧不斷的給客戶(hù)帶來(lái)驚喜。創(chuàng)新互聯(lián)建站推出唐河免費(fèi)做網(wǎng)站回饋大家。
Android的主線程是UI線程,在Android中,四大組件運(yùn)行在主線程中,在主線程中做耗時(shí)操作會(huì)導(dǎo)致程序出現(xiàn)卡頓甚至出現(xiàn)ANR異常,一個(gè)基本常識(shí)就是將耗時(shí)操作放到子線程中去處理,然后通過(guò)Handler回調(diào)到主線程。
有三點(diǎn)還需要注意:
因?yàn)樗拇蠼M件運(yùn)行在一個(gè)主線程中,那么若果當(dāng)前界面在顯示的時(shí)候,后臺(tái)的activity仍有處理邏輯再運(yùn)行的話,仍然會(huì)造成當(dāng)前界面的卡頓。
通過(guò)Handler回調(diào)到主線程只是避免程序出現(xiàn)ANR的第一步,必須要注意handler中邏輯處理的耗時(shí),如果將很多消息都扔給了handler,那么也會(huì)給主線程造成壓力,導(dǎo)致程序運(yùn)行卡頓。
四大組件、Handler都是在一個(gè)線程中,那么主線程在同一時(shí)刻不可能發(fā)送兩個(gè)廣播,換句話說(shuō)就是若果能夠保證所有的廣播都是在主線程中發(fā)送,那么廣播內(nèi)部其實(shí)不需要加上對(duì)異步操作的處理。
[img]在Android中有主線程和子線程的區(qū)分。主線程又稱(chēng)為UI線程,主要是處理一些和界面相關(guān)的事情,而子線程主要是用于處理一些耗時(shí)比較大的一些任務(wù),例如一些網(wǎng)絡(luò)操作,IO請(qǐng)求等。如果在主線程中處理這些耗時(shí)的任務(wù),則有可能會(huì)出現(xiàn)ANR現(xiàn)象(App直接卡死)。
線程池,從名字的表明含義上我們知道線程池就是包含線程的一個(gè)池子,它起到新建線程、管理線程、調(diào)度線程等作用。
既然Android中已經(jīng)有了線程的概念,那么為什么需要使用線程池呢?我們從兩個(gè)方面給出使用線程池的原因。
在Android中線程池就是ThreadPoolExecutor對(duì)象。我們先來(lái)看一下ThreadPoolExecutor的構(gòu)造函數(shù)。
我們分別說(shuō)一下當(dāng)前的幾個(gè)參數(shù)的含義:
第一個(gè)參數(shù)corePoolSize為 核心線程數(shù) ,也就是說(shuō)線程池中至少有這么多的線程,即使存在的這些線程沒(méi)有執(zhí)行任務(wù)。但是有一個(gè)例外就是,如果在線程池中設(shè)置了allowCoreThreadTimeOut為true,那么在 超時(shí)時(shí)間(keepAliveTime) 到達(dá)后核心線程也會(huì)被銷(xiāo)毀。
第二個(gè)參數(shù)maximumPoolSize為 線程池中的最大線程數(shù) 。當(dāng)活動(dòng)線程數(shù)達(dá)到這個(gè)數(shù)后,后續(xù)添加的新任務(wù)會(huì)被阻塞。
第三個(gè)參數(shù)keepAliveTime為 線程的保活時(shí)間 ,就是說(shuō)如果線程池中有多于核心線程數(shù)的線程,那么在線程沒(méi)有任務(wù)的那一刻起開(kāi)始計(jì)時(shí),如果超過(guò)了keepAliveTime,還沒(méi)有新的任務(wù)過(guò)來(lái),則該線程就要被銷(xiāo)毀。同時(shí)如果設(shè)置了allowCoreThreadTimeOut為true,該時(shí)間也就是上面第一條所說(shuō)的 超時(shí)時(shí)間 。
第四個(gè)參數(shù)unit為 第三個(gè)參數(shù)的計(jì)時(shí)單位 ,有毫秒、秒等。
第五個(gè)參數(shù)workQueue為 線程池中的任務(wù)隊(duì)列 ,該隊(duì)列持有由execute方法傳遞過(guò)來(lái)的Runnable對(duì)象(Runnable對(duì)象就是一個(gè)任務(wù))。這個(gè)任務(wù)隊(duì)列的類(lèi)型是BlockQueue類(lèi)型,也就是阻塞隊(duì)列,當(dāng)隊(duì)列的任務(wù)數(shù)為0時(shí),取任務(wù)的操作會(huì)被阻塞;當(dāng)隊(duì)列的任務(wù)數(shù)滿(mǎn)了(活動(dòng)線程達(dá)到了最大線程數(shù)),添加操作就會(huì)阻塞。
第六個(gè)參數(shù)threadFactory為 線程工廠 ,當(dāng)線程池需要?jiǎng)?chuàng)建一個(gè)新線程時(shí),使用線程工廠來(lái)給線程池提供一個(gè)線程。
第七個(gè)參數(shù)handler為 拒絕策略 ,當(dāng)線程池使用有界隊(duì)列時(shí)(也就是第五個(gè)參數(shù)),如果隊(duì)列滿(mǎn)了,任務(wù)添加到線程池的時(shí)候的一個(gè)拒絕策略。
可以看到FixedThreadPool的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出FixedThreadPool的幾個(gè)特點(diǎn):
可以看到CacheThreadPool的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出CacheThreadPool的幾個(gè)特點(diǎn):
可以看到ScheduledThreadPoolExecutor的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出ScheduledThreadPoolExecutor的幾個(gè)特點(diǎn):
可以看到SingleThreadExecutor的構(gòu)建調(diào)用了ThreadPoolExecutor的構(gòu)造函數(shù)。從上面的調(diào)用中可以看出SingleThreadExecutor的幾個(gè)特點(diǎn):
多線程作為Android開(kāi)發(fā)中相對(duì)而言較為高階的知識(shí),其中用到相關(guān)的知識(shí)點(diǎn)是非常的多,所以在我們需要進(jìn)行設(shè)計(jì)或者寫(xiě)多線程的代碼就必須要進(jìn)行相對(duì)謹(jǐn)慎的處理,這樣就由必要對(duì)其要有著比較系統(tǒng)化的認(rèn)知
我們一般將Android應(yīng)用分成為兩種:主線程和工作線程;主線程主要是用來(lái)進(jìn)行初始化UI,而工作線程主要是進(jìn)行耗時(shí)操作,例如讀取數(shù)據(jù)庫(kù),網(wǎng)絡(luò)連接等
Android系統(tǒng)是以進(jìn)程為單位來(lái)對(duì)應(yīng)用程序資源進(jìn)行限制,這個(gè)問(wèn)題的可以解釋為:一個(gè)進(jìn)程最多能夠開(kāi)幾個(gè)線程?最好能開(kāi)幾個(gè)?但實(shí)則這個(gè)是沒(méi)有上限這一說(shuō),主要是因?yàn)橘Y源的限制
Android中關(guān)于主線程的理解:Android的主線程是UI線程,在Android中,四大組件運(yùn)行在主線程中,在主線程中做耗時(shí)操作會(huì)導(dǎo)致程序出現(xiàn)卡頓甚至出現(xiàn)ANR異常,一個(gè).
在一個(gè)程序中,這些獨(dú)立運(yùn)行的程序片斷叫作“線程”(Thread),利用它編程的概念就叫作“多線程處理”。多線程處理一個(gè)常見(jiàn)的例子就是用戶(hù)界面。
線程總的來(lái)就是進(jìn)程的一個(gè)實(shí)體,是CPU進(jìn)行分派和調(diào)度的基本單位,擁有著比進(jìn)程更小且能夠獨(dú)立運(yùn)行的基本單位,線程本身基本上是不擁有系統(tǒng)資源,僅擁有一點(diǎn)在運(yùn)行過(guò)程中必須擁有的資源,但它可與同屬一個(gè)進(jìn)程中的其他進(jìn)程進(jìn)行共享其所擁有的所有資源
線程狀態(tài)有些地方將之分為5中狀態(tài),而且在Java Jdk中線程被其定義為6中狀態(tài),我們可以對(duì)其進(jìn)行類(lèi)比
普遍定義的5中狀態(tài):新建,就緒,運(yùn)行,阻塞, 死亡
Java Jdk 定義狀態(tài)
線程阻塞是指在某一時(shí)刻的某一個(gè)線程在進(jìn)行運(yùn)行一段代碼的情況下,突然另一個(gè)線程也要進(jìn)行運(yùn)行,但在運(yùn)行過(guò)程中,那個(gè)線程執(zhí)行完全運(yùn)行之前,另一個(gè)線程是不可能獲取到CPU的執(zhí)行權(quán),就會(huì)導(dǎo)致線路阻塞的出現(xiàn)
死鎖也稱(chēng)之為抱死,意思就是說(shuō)一個(gè)進(jìn)程鎖定了另外一個(gè)進(jìn)程所需要的頁(yè)或表是,但第二個(gè)進(jìn)程同時(shí)又鎖定了第一個(gè)進(jìn)程所需的一頁(yè),這樣就會(huì)出現(xiàn)死鎖現(xiàn)象
簡(jiǎn)要介紹實(shí)現(xiàn)線程的三種方式:繼承Thread,實(shí)現(xiàn)runnable,實(shí)現(xiàn)callable。這里有一點(diǎn)需要注意的是,實(shí)現(xiàn)callable是與線程池相關(guān)聯(lián)的而callable很重要的一個(gè)特性是其帶有返回值。當(dāng)我們只需實(shí)現(xiàn)單線程時(shí)實(shí)現(xiàn)runnable更加利于線程程序的拓展
在線程開(kāi)啟之前進(jìn)行調(diào)用 thread.setDaemon(true); 將thread設(shè)定成當(dāng)前線程中的守護(hù)線程 使用案例
線程讓步【yield方法】讓當(dāng)前線程釋放CPU資源,讓其他線程搶占
這種具體某個(gè)對(duì)象鎖 wait notify 方法與Condition 的 await以及signal方法類(lèi)似; 全面這種方法的阻塞等待都可以是釋放鎖,而且在喚醒后,這種線程都是能夠獲取鎖資源的,而這個(gè)門(mén)栓就跟閥門(mén)類(lèi)似