導航:首頁 > 操作系統 > android緩存池

android緩存池

發布時間:2022-07-05 12:43:08

android Studio的JVM內存不足問題怎麼解決

找到Eclipse安裝文件下的eclipse.ini配置文件
通常裡面都是寫的-vmargs-Xms40m-Xmx256m
-vmargs:說明後面是VM的參數
-Xms40m:虛擬機佔用系統的最小內存
Xmx256m:虛擬機佔用系統的最大內存
-XX:PermSize:最小堆大小.一般報內存不足時,都是說這個太小,堆空間剩餘小於5%就會警告,建議把這個稍微設大一點,不過要視自己機器內存大小來設置-XX:PermSize:最大堆大小.這個也適當大些,另外把裡面的參數改為:
-vmargs
-Xms128M
-Xmx512M
-XX:PermSize=128M
-XX:MaxPermSize=256M
1、設置Eclipse內存使用情況
修改eclipse根目錄下的eclipse.ini文件
-vmargs //虛擬機設置
-Xms40m
-Xmx256m
-XX:PermSize=128M //非堆內存設置
-XX:MaxPermSize=256M
2、JVM內存設置
打開eclipse window-preferences-java -Installed JREs -Edit -Default VM Arguments 在VM自變數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m3, Tomcat內存設置
打開Tomcat根目錄下的bin文件夾,編輯catalina.bat 修改為:set JAVA_OPTS= -Xms256m -Xmx512m下面是這幾個設置的一些背景知識:
1 堆(Heap)和非堆(Non- heap)內存
按照官方的說法:「Java 虛擬機具有一個堆,堆是運行時數據區域,所有類實例和數組的內存均從此處分配。堆是在 Java 虛擬機啟動時創建的。」「在JVM中堆之外的內存稱為非堆內存(Non-heap memory)」。可以看出JVM主要管理兩種類型的內存:堆和非堆。簡單來說堆就是Java代碼可及的內存,是留給開發人員使用的;非堆就是JVM留給 自己用的,所以方法區、JVM內部處理或優化所需的內存(如JIT編譯後的代碼緩存)、每個類結構(如運行時常數池、欄位和方法數據)以及方法和構造方法 的代碼都在非堆內存中。 2 堆內存分配
JVM初始分配的內存由-Xms指定,默認是物理內存的1/64;JVM最大分配的內存由-Xmx指定,默認是物理內存的1/4。默認空餘堆內存 小於 40%時,JVM就會增大堆直到-Xmx的最大限制;空餘堆內存大於70%時,JVM會減少堆直到-Xms的最小限制。因此伺服器一般設置-Xms、 -Xmx相等以避免在每次GC 後調整堆的大小。
3、非堆內存分配
JVM使用-XX:PermSize設置非堆內存初始值,默認是物理內存的1/64;由XX:MaxPermSize設置最大非堆內存的大小,默認是物理內存的1/4。
4、JVM內存限制(最大值)
首先JVM內存首先受限於實際的最大物理內存,假設物理內存無限大的話,JVM內存的最大值跟操作系統有很大的關系。簡單的說就32位處理器雖然 可控內存空間有4GB,但是具體的操作系統會給一個限制,這個限制一般是2GB-3GB(一般來說Windows系統下為1.5G-2G,Linux系統 下為 2G-3G),而64bit以上的處理器就不會有限制了

Ⅱ (in+1)mod n =out為什麼表示緩沖區滿 而為什麼in=out又表示緩沖池空

可以看看這一段前半部分,說到in和out都是指針,in=out就是,輸入的指針指的位置和輸出指針指的位置一致,也就是一放進去就被拿出來了,所以緩存池一直為空。(in+1)就是輸入指針一直在緩存池中移動,但是緩存池有限,輸入到最後就要回到最開始的位置,解決就是對緩存池大小取余數就能把指針一直循環下去,也就是(in+1)mod n,(in+1)mod n = out代表輸入循環了至少一圈,和out又指向了同一個位置,相當於out慢了in整整一圈,所以緩存池滿了,in需要等out取出後才能繼續輸入。其實你把等號理解成指針指向同樣的地方,就很好理解了。我也才上到這里,如果有哪裡理解錯的希望指正。

Ⅲ android中的線程池 怎麼用

//在Android中實現線程池,首先需要實現一個線程工廠(ThreadFactory)的子類,具體實現方式如下所示(PriorityThreadFactory.Java):
import android.os.Process;
/**
* A thread factory that create threads with a given thread priority
* @author jony
* @version 1.0
*/
public class PriorityThreadFactory implements ThreadFactory{
private final String mName;
private final int mPriority;
private final AtomicInteger mNumber = new AtomicInteger();

public PriorityThreadFactory(String name, int priority) {
mName = name;// 線程池的名稱
mPriority = priority;//線程池的優先順序
}
@Override
public Thread newThread(Runnable r) {
return new Thread(r, mName +"-"+mNumber.getAndIncrement()){
@Override
public void run() {
// 設置線程的優先順序
Process.setThreadPriority(mPriority);
super.run();
}
};
}
}
//以上是創建線程池的一個工具類,接下來為大家介紹本篇文章的重點,線程池的實現方式,具體實現方式如下所示(MyThreadPool.java):
package com.tcl.actionbar;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
package com.tcl.actionbar;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.ThreadFactory;

// 線程池的實現方式
public class MyThreadPool {
private final static int POOL_SIZE = 4;// 線程池的大小最好設置成為CUP核數的2N
private final static int MAX_POOL_SIZE = 6;// 設置線程池的最大線程數
private final static int KEEP_ALIVE_TIME = 4;// 設置線程的存活時間
private final Executor mExecutor;
public MyThreadPool() {
// 創建線程池工廠
ThreadFactory factory = new PriorityThreadFactory("thread-pool", android.os.Process.THREAD_PRIORITY_BACKGROUND);
// 創建工作隊列
BlockingQueue<Runnable> workQueue = new LinkedBlockingDeque<Runnable>();
mExecutor = new ThreadPoolExecutor(POOL_SIZE, MAX_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, workQueue, factory);
}
// 在線程池中執行線程
public void submit(Runnable command){
mExecutor.execute(command);
}
}
//自己覺得這個·代碼不錯,我就只是將它搬了過來,實際代碼地址:http://blog.csdn.net/weihan1314/article/details/7983725

Ⅳ android中handler和service的區別是什麼

任務、進程和線程
關於Android中的組件和應用,之前涉及,大都是靜態的概念。而當一個應用運行起來,就難免會需要關心進程、線程這樣的概念。在Android中,組件的動態運行,有一個最與眾不同的概念,就是Task,翻譯成任務,應該還是比較順理成章的。
Task的介入,最主要的作用,是將組件之間的連接,從進程概念的細節中剝離出來,可以以一種不同模型的東西進行配置,在很多時候,能夠簡化上層開發人員的理解難度,幫助大家更好的進行開發和配置。

任務
在SDK中關於Task(guide/topics/fundamentals.html#acttask),有一個很好的比方,說,Task就相當於應用(application)的概念。在開發人員眼中,開發一個Android程序,是做一個個獨門獨戶的組件,但對於一般用戶而言,它們感知到的,只是一個運行起來的整體應用,這個整體背後,就是Task。
Task,簡單的說,就是一組以棧的模式聚集在一起的Activity組件集合。它們有潛在的前後驅關聯,新加入的Activity組件,位於棧頂,並僅有在棧頂的Activity,才會有機會與用戶進行交互。而當棧頂的 Activity完成使命退出的時候,Task會將其退棧,並讓下一個將跑到棧頂的Activity來於用戶面對面,直至棧中再無更多 Activity,Task結束。

事件 Task棧
點開Email應用,進入收件箱(Activity A) A
選中一封郵件,點擊查看詳情(Activity B) AB
點擊回復,開始寫新郵件(Activity C) ABC
寫了幾行字,點擊選擇聯系人,進入選擇聯系人界面(Activity D) ABCD
選擇好了聯系人,繼續寫郵件 ABC
寫好郵件,發送完成,回到原始郵件 AB
點擊返回,回到收件箱 A
退出Email程序 null

如上表所示,是一個實例。從用戶從進入郵箱開始,到回復完成,退出應用整個過程的Task棧變化。這是一個標準的棧模式,對於大部分的狀況,這樣的Task 模型,足以應付,但是,涉及到實際的性能、開銷等問題,就會變得殘酷許多。比如,啟動一個瀏覽器,在Android中是一個比較沉重的過程,它需要做很多初始化的工作,並且會有不小的內存開銷。但與此同時,用瀏覽器打開一些內容,又是一般應用都會有的一個需求。設想一下,如果同時有十個運行著的應用(就會對應著是多個Task),都需要啟動瀏覽器,這將是一個多麼殘酷的場面,十個Task棧都堆積著很雷同的瀏覽器Activity,是多麼華麗的一種浪費啊。於是你會有這樣一種設想,瀏覽器Activity,可不可以作為一個單獨的Task而存在,不管是來自那個Task的請求,瀏覽器的Task,都不會歸並過去。這樣,雖然瀏覽器Activity本身需要維系的狀態更多了,但整體的開銷將大大的減少,這種舍小家為大家的行為,還是很值得歌頌的。
如此值得歌頌的行為,Android當然會舉雙手支持的。在Android中,每一個Activity的Task模式,都是可以由Activity提供方(通過配置文件...)和Activity使用方(通過Intent中的flag信息...)進行配置和選擇。當然,使用方對Activity的控制力,是限定在提供方允許的范疇內進行,提供方明令禁止的模式,使用方是不能夠越界使用的。
在SDK中(guide/topics/fundamentals.html#acttask),將兩者實現Task模式配置的方式,寫的非常清晰了,我再很絮叨挑選一些來解釋一下(完整可配置項,一定要看SDK,下面只是其中常用的若干項...)。提供方對組件的配置,是通過配置文件(Manifest)<activity>項來進行的,而調用方,則是通過Intent對象的flag進行抉擇的。相對於標準的Task棧的模式,配置的主要方向有兩個:一則是破壞已有棧的進出規則,或樣式;另一則是開辟新Task棧完成本應在同一Task棧中完成的任務。
對於應用開發人員而言,<activity>中的launchMode屬性,是需要經常打交道的。它有四種模式:"standard", "singleTop", "singleTask", "singleInstance"。
standard模式,是默認的也是標準的Task模式,在沒有其他因素的影響下,使用此模式的Activity,會構造一個Activity的實例,加入到調用者的Task棧中去,對於使用頻度一般開銷一般什麼都一般的Activity而言,standard模式無疑是最合適的,因為它邏輯簡單條理清晰,所以是默認的選擇。
而singleTop模式,基本上於standard一致,僅在請求的Activity正好位於棧頂時,有所區別。此時,配置成singleTop的Activity,不再會構造新的實例加入到Task棧中,而是將新來的Intent發送到棧頂Activity中,棧頂的Activity可以通過重載onNewIntent來處理新的Intent(當然,也可以無視...)。這個模式,降低了位於棧頂時的一些重復開銷,更避免了一些奇異的行為(想像一下,如果在棧頂連續幾個都是同樣的Activity,再一級級退出的時候,這是怎麼樣的用戶體驗...),很適合一些會有更新的列表Activity展示。一個活生生的實例是,在 Android默認提供的應用中,瀏覽器(Browser)的書簽Activity(BrowserBookmarkPage),就用的是singleTop。
singleTop模式,雖然破壞了原有棧的邏輯(復用了棧頂,而沒有構造新元素進棧...),但並未開辟專屬的Task。而singleTask,和singleInstance,則都採取的另闢Task的蹊徑。標志為singleTask的Activity,最多僅有一個實例存在,並且,位於以它為根的Task中。所有對該Activity的請求,都會跳到該Activity的Task中展開進行。singleTask,很象概念中的單件模式,所有的修改都是基於一個實例,這通常用在構造成本很大,但切換成本較小的Activity中。在Android源碼提供的應用中,該模式被廣泛的採用,最典型的例子,還是瀏覽器應用的主Activity(名為Browser...),它是展示當前tab,當前頁面內容的窗口。它的構造成本大,但頁面的切換還是較快的,於 singleTask相配,還是挺天作之合的。
相比之下,singleInstance顯得更為極端一些。在大部分時候singleInstance與singleTask完全一致,唯一的不同在於,singleInstance的Activity,是它所在棧中僅有的一個Activity,如果涉及到的其他Activity,都移交到其他Task中進行。這使得singleInstance的Activity,像一座孤島,徹底的黑盒,它不關注請求來自何方,也不計較後續由誰執行。在Android默認的各個應用中,很少有這樣的Activity,在我個人的工程實踐中,曾嘗試在有道詞典的快速取詞Activity中採用過,是因為我覺得快速取詞入口足夠方便(從notification中點選進入),並且會在各個場合使用,應該做得完全獨立。
除了launchMode可以用來調配Task,<activity>的另一屬性taskAffinity,也是常常被使用。taskAffinity,是一種物以類聚的思想,它傾向於將taskAffinity屬性相同的Activity,扔進同一個Task中。不過,它的約束力,較之launchMode而言,弱了許多。只有當<activity>中的allowTaskReparen ting設置為true,抑或是調用方將Intent的flag添加FLAG_ACTIVITY_NEW_TASK屬性時才會生效。如果有機會用到Android的Notification機制就能夠知道,每一個由notification進行觸發的Activity,都必須是一個設成FLAG_ACTIVITY_NEW_TASK的Intent來調用。這時候,開發者很可能需要妥善配置taskAffinity屬性,使得調用起來的Activity,能夠找到組織,在同一taskAffinity的Task中進行運行。

進程
在大多數其他平台的開發中,每個開發人員對自己應用的進程模型都有非常清晰的了解。比如,一個控制台程序,你可以想見它從main函數開始啟動一個進程,到 main函數結束,進程執行完成退出;在UI程序中,往往是有一個消息循環在跑,當接受到Exit消息後,退出消息循環結束進程。在該程序運行過程中,啟動了什麼進程,和第三方進程進行通信等等操作,每個開發者都是心如明鏡一本帳算得清清楚楚。進程邊界,在這里,猶如國界一般,每一次穿越都會留下深深的印跡。
在Android程序中,開發人員可以直接感知的,往往是Task而已。倍感清晰的,是組件邊界,而進程邊界變得難以琢磨,甚至有了進程託管一說。Android中不但剝奪了手工鍛造內存權力,連手工處置進程的權責,也毫不猶豫的獨佔了。
當然,Android隱藏進程細節,並不是刻意為之,而是自然而然水到渠成的。如果,我們把傳統的應用稱為面向進程的開發,那麼,在Android中,我們做得就是面向組件的開發。從前面的內容可以知道,Android組件間的跳轉和通信,都是在第三方介入的前提下進行,正由於這種介入,使得兩個組件一般不會直接發生聯系(於Service的通信,是不需要第三方介入的,因此Android把它全部假設成為穿越進程邊界,統一基於RPC來通信,這樣,也是為了掩蓋進程細節...),其中是否穿越進程邊界也就變得不重要。因此,如果這時候,還需要開發者關注進程,就會變得很奇怪,很費解,乾脆,Android將所有的進程一並託管去了,上層無須知道進程的生死和通信細節。
在Android的底層,進程構造了底部的一個運行池,不僅僅是Task中的各個Activity組件,其他三大組件Service、Content Provider、Broadcast Receiver,都是寄宿在底層某個進程中,進行運轉。在這里,進程更像一個資源池(概念形如線程池,上層要用的時候取一個出來就好,而不關注具體取了哪一個...),只是為了承載各個組件的運行,而各個組件直接的邏輯關系,它們並不關心。但我們可以想像,為了保證整體性,在默認情況下,Android肯定傾向於將同一Task、同一應用的各個組件扔進同一個進程內,但是當然,出於效率考慮,Android也是允許開發者進行配置。
在Android中,整體的<application>(將影響其中各個組件...)和底下各個組件,都可以設置<process>屬性,相同<process>屬性的組件將扔到同一個進程中運行。最常見的使用場景,是通過配置<application>的process屬性,將不同的相關應用,塞進一個進程,使得它們可以同生共死。還有就是將經常和某個Service組件進行通信的組件,放入同一個進程,因為與Service通信是個密集操作,走的是RPC,開銷不小,通過配置,可以變成進程內的直接引用,消耗頗小。
除了通過<process>屬性,不同的組件還有一些特殊的配置項,以Content Provider為例(通過<provider>項進行配置...)。<provider>項有一個mutiprocess的屬性,默認值為false,這意味著Content Provider,僅會在提供該組件的應用所在進程構造一個實例,第三方想使用就需要經由RPC傳輸數據。這種模式,對於構造開銷大,數據傳輸開銷小的場合是非常適用的,並且可能提高緩存的效果。但是,如果是數據傳輸很大,抑或是希望在此提高傳輸的效率,就需要將mutiprocess設置成true,這樣,Content Provider就會在每一個調用它的進程中構造一個實例,避免進程通信的開銷。
既然,是Android系統幫助開發人員託管了進程,那麼就需要有一整套紛繁的演算法去執行回收邏輯。Android中各個進程的生死,和運行在其中的各個組件有著密切的聯系,進程們依照其上組件的特點,被排入一個優先順序體系,在需要回收時,從低優先順序到高優先順序回收。Android進程共分為五類優先順序,分別是:Foreground Process, Visible Process, Service Process, Background Process, Empty Process。顧名思義不難看出,這說明,越和用戶操作緊密相連的,越是正與用戶交互的,優先順序越高,越難被回收。具體詳情,參見:guide/topics/fundamentals.html#proclife。
有了優先順序,還需要有良好的回收時機。回收太早,緩存命中概率低可能引起不斷的創造進程銷毀進程,池的優勢盪然無存;回收的太晚,整體開銷大,系統運行效率降低,好端端的法拉利可能被糟蹋成一枚QQ老爺車。Android的進程回收,最重要的是考量內存開銷,以及電量等其他資源狀況,此外每個進程承載的組件數量、單個應用開辟的進程數量等數量指標,也是作為衡量的一個重要標識。另外,一些運行時的時間開銷,也被嚴格監控,啟動慢的進程會很被強行kill掉。Android會定時檢查上述參數,也會在一些很可能發生進程回收的時間點,比如某個組件執行完成後,來做回收的嘗試。
從用戶體驗角度來看,Android的進程機制,會有很可喜的一面,有的程序啟動速度很慢,但是在資源充沛的前提下,你反復的退出再使用,則啟動變得極其快速(進程沒死,只是從後台弄到了前台),這就是拜進程託管所賜的。當然,可喜的另一面就是可悲了,Android的託管演算法,還時不時的展現其幼稚的一面,明明用戶已經明顯感覺到操作系統運行速度下降了,打開任務管理器一看,一票應用還生龍活虎的跳躍著,必須要手動幫助它們終結生命找到墳墓,這使得任務管理器基本成為Android的裝機必備軟體。
從開發角度上來看,Android這套進程機制,解放了開發者的手腳。開發人員不需要處心積慮的構造一個後台進程偷偷默默監聽某個時間,並嘗試用各種各樣的守護手段,把自己的進程鍛造的猶如不死鳥一輝一般,進程生死的問題,已經原理了普通開發人員需要管理的范疇內。但同時,於GC和人肉內存管理的爭議一樣,所有開發人員都不相信演算法能比自己做得效率更高更出色。但我一直堅信一點,所有效率的優勢都會隨著演算法的不斷改良硬體的不斷提升而消失殆盡,只有開發模式的簡潔不會隨時間而有任何變化。

組件生命周期
任何架構上的變化,都會引起上層開發模式的變化,Android的進程模型,雖然使開發者不再需要密切關注進程的創建和銷毀的時機,但仍然需要關注這些時間點對組件的影響。比如,你可能需要在進程銷毀之前,將寫到內存上的內容,持久化到硬碟上,這就需要關注進程退出前發生的一些事件。
在Android中,把握這些時間點,就必須了解組件生命周期(Components Lifecycles)。所謂組件的生命在周期,就是在組件在前後台切換、被用戶創建退出、被系統回收等等事件發生的時候,會有一些事件通知到對應組件上,開發人員可以選擇性的處理這些事件在對應的時間點上來完成一些附加工作。
除Content Provider,其他組件都會有生命周期的概念,都需要依照這個模型定時定點處理一些狀況,全部內容參見:guide/topics/fundamentals.html#lcycles。在這里,擒賊先擒王,還是拿Activity出來作楷模。

繼續偷圖,來自SDK。一個自然的Activity生命旅途,從onCreate開始,到onDestroy消亡。但月有陰晴圓缺組件有禍福旦夕,在系統需要的時候且組件位於後台時,所在的進程隨時可能為國捐軀被回收,這就使得知道切入後台這個事情也變得很重要。
當組件進入棧頂,與用戶開始交互,會調用onResume函數,類似,當退出棧頂,會有onPause函數被呼喚。onResume和onPause可以處理很多事情,最常規的,就是做一些文件或設置項的讀寫工作。因為,在該組件不再前台運行的時候,可能別的組件會需要讀寫同樣一份文件和設置,如果不再onResume做刷新工作,用的可能就是一份臟數據了(當然,具體情況,還需要具體分析,如果文件不會被多頭讀寫,可以放到onCreate裡面去做讀工作)。
除了前述切入後台會被其他組件騷擾的問題,另外,死無定因也是件很可怕的事情。在Android中,組件都有兩種常見的死法,一種是自然消亡,比如,棧元素ABC,變成AB了,C組件就自然消亡了。這種死發輕如鴻毛,不需要額外關心。但另一種情況,就是被系統回收,那是死的重如泰山,為國捐軀嘛。
但這種捐軀的死法,對用戶來說,比較費解。想像一下,一款游戲,不能存檔,你一直玩啊玩,三天三夜沒合眼,這時候你mm打來電話鼓勵一下,你精神抖擻的准備再接再厲,卻發現你的游戲進程,在切入後台之後,被系統回收了,一夜回到解放前三天努力成為一場泡影,你會不會想殺做游戲的人,會不會會不會會不會,一定會嘛。這時候,如果沒有Activity生命周期這碼事,游戲程序員一定是被冤死的,成了Android的替罪羊。但是,Android的組件是有生命周期的, 如果真的發生這樣情況,不要猶豫,去殺開發的程序員吧。
為了逃生,程序員們有一塊免死金牌,那就是Android的state機制。所謂state,就是開發人員將一些當前運行的狀態信息存放在一個Bundle對象裡面,這是一個可序列化鍵值對集合。如果該Activity組件所處的進程需要回收,Android核心會將其上Activity組件的Bundle對象持久化到磁碟上,當用戶回到該Activity時候,系統會重新構造該組件,並將持久化到磁碟上的Bundle對象恢復。有了這樣的持久化的狀態信息,開發人員可以很好的區分具體死法,並有機會的使得死而復生的Activity恢復到死前狀態。開發者應該做的,是通過onSaveInstanceState函數把需要維系的狀態信息(在默認的狀態下,系統控制項都會自己保存相關的狀態信息,比如TextView,會保存當前的Text信息,這都不需要開發人員擔心...),寫入到Bundle對象,然後在onRestoreInstanceState函數中讀取並恢復相關信息(onCreate,onStart,也都可以處理...)。

線程
讀取數據,後台處理,這些猥瑣的伙計,自然少不了線程的參與。在Android核心的調度層面,是不屑於考量線程的,它關注的只有進程,每一個組件的構造和處理,都是在進程的主線程上做的,這樣可以保證邏輯的足夠簡單。多線程,往往都是開發人員需要做的。
Android的線程,也是通過派生Java的Thread對象,實現Run方法來實現的。但當用戶需要跑一個具有消息循環的線程的時候,Android有更好的支持,來自於Handler和Looper。Handler做的是消息的傳送和分發,派生其handleMessage函數,可以處理各種收到的消息,和win開發無異。Looper的任務,則是構造循環,等候退出或其他消息的來臨。在Looper的SDK頁面,有一個消息循環線程實現的標准範例,當然,更為標準的方式也許是構造一個HandlerThread線程,將它的Looper傳遞給Handler。
在Android中,Content Provider的使用,往往和線程掛鉤,誰讓它和數據相關呢。在前面提到過,Content Provider為了保持更多的靈活性,本身只提供了同步調用的介面,而由於非同步對Content Provider進行增刪改查是一個常做操作,Android通過AsyncQueryHandler對象,提供了非同步介面。這是一個Handler的子類,開發人員可以調用startXXX方法發起操作,通過派生onXXXComplete方法,等待執行完畢後的回調,從而完成整個非同步調用的流程,十分的簡約明了。

實現
整個任務、進程管理的核心實現,盡在ActivityManagerService中。上一篇說到,Intent解析,就是這個ActivityManagerService來負責的,其實,它是一個很名不副實的類,因為雖然名為Activity的Manager Service,但它管轄的范圍,不只是Activity,還有其他三類組件,和它們所在的進程。
在ActivityManagerService中,有兩類數據結構最為醒目,一個是ArrayList,另一個是HashMap。 ActivityManagerService有大量的ArrayList,每一個組件,會有多個ArrayList來分狀態存放。調度工作,往往就是從一個ArrayList裡面拿出來,找個方法調一調,然後扔到另一個ArrayList裡面去,當這個組件沒對應的ArrayList放著的時候,說明它離死不遠了。HashMap,是因為有組件是需要用名字或Intent信息做定位的,比如Content Provider,它的查找,都是依據Uri,有了HashMap,一切都順理成章了。
ActivityManagerService用一些名曰xxxRecord的數據結構,來表達各個存活的組件。於是就有了,HistoryRecord(保存Activity信息的,之所以叫History,是相對Task棧而言的...),ServiceRecord,BroadcastRecord,ContentProviderRecord,TaskRecord,ProcessRecord,等等。
值得注意的,是TaskRecord,我們一直再說,Task棧這樣的概念,其實,真實的底層,並不會在TaskRecord中,維系一個Activity 的棧。在ActivityManagerService中,各個任務的Activity,都以HistoryRecord的形式,集中存放在一個 ArrayList中,每個HistoryRecord,會存放它所在TaskRecord的引用。當有一個Activity,執行完成,從概念上的 Task棧中退出,Android是通過從當前HistoryRecord位置往前掃描同一個TaskRecord的HistoryRecord來完成的。這個設計,使得上層很多看上去邏輯很復雜的Task體系,在實現變得很統一而簡明,值得稱道。
ProcessRecord,是整個進程託管實現的核心,它存放有運行在這個進程上,所有組件的信息,根據這些信息,系統有一整套的演算法來決議如何處置這個進程,如果對回收演算法感興趣,可以從ActivityManagerService的trimApplications函數入手來看。
對於開發者來說,去了解這部分實現,主要是可以幫助理解整個進程和任務的概念,如果覺得這塊理解的清晰了,就不用去碰ActivityManagerService這個龐然大物了。

================
這是轉載的 ,感覺比一樓說的好

=============
一下是自己的

服務(Service)需要配置 才能使用
線程 使用就不說了
hanler ,是用來進行消息隊列的一個東東,handler 可以用來更新控制項的顯示 ,以及線程之間的通信,
service只能啟動後台,屬於應用組件之一

Ⅳ 請問頁面緩存池是什麼東西

就是存放你IE上瀏覽的東西的戰時空間
一般來說,這個空間越大速度越快,
可以相映的設置大一點

Ⅵ Android的App中線程池的使用,具體使用多少個線程池

1.可以根據cpu數來配。
2. 其實這個問題只是線程池的使用理解上來做的,具體看功能。
3. 所謂線程池就是一種對象池緩存優化技術,當任務量非常巨大的時候具有減少內存開銷的作用。

Ⅶ android 什麼時候使用弱指針

使用bitmap時使用弱引用。android學習手冊中有關於listview中有大量圖片,載入bitmap時使用弱引用載入的小例子。

下面介紹來自於android學習手冊,android學習手冊包含9個章節,108個例子,源碼文檔隨便看,例子都是可交互,可運行,源碼採用android studio目錄結構,高亮顯示代碼,文檔都採用文檔結構圖顯示,可以快速定位。360手機助手中下載,排在第三、四個。

使用bitmap時容易引起oom,雖然我們可以在bitmap不適用的時候通過recycle方法釋放bitmap佔用的內存,但是如果這個方法調用的時間點不合理,很容易引起 use a recycle bitmap的異常。

對此,可以使用弱引用來管理bitmap。將所有用到的bitmap對象放到一個hashmap中,用弱引用來保存,如果再用到這個bitmap的時候,根據相應的key直接取出來,相當於一個高速緩存池。如果確定不再使用的時候手動將其recycle,保證這個程序不會重復創建過多的bitmap對象。此外弱引用對象可以在系統內存不足的時候自動被系統回收。


如果一個對象只具有軟引用,那麼如果內存空間足夠,垃圾回收器就不會回收它;如果內存空間不足了,就會回收這些對象的內存。只要垃圾回收器沒有回收它,該對象就可以被程序使用。軟引用可用來實現內存敏感的高速緩存。軟引用可以和一個引用隊列(ReferenceQueue)聯合使用,如果軟引用所引用的對象被垃圾回收,Java虛擬機就會把這個軟引用加入到與之關聯的引用隊列中。

如果一個對象只具有弱引用,那麼在垃圾回收器線程掃描的過程中,一旦發現了只具有弱引用的對象,不管當前內存空間足夠與否,都會回收它的內存。不過,由於垃圾回收器是一個優先順序很低的線程,因此不一定會很快發現那些只具有弱引用的對象。弱引用也可以和一個引用隊列(ReferenceQueue)聯合使用,如果弱引用所引用的對象被垃圾回收,Java虛擬機就會把這個弱引用加入到與之關聯的引用隊列中。

弱引用與軟引用的根本區別在於:只具有弱引用的對象擁有更短暫的生命周期,可能隨時被回收。而只具有軟引用的對象只有當內存不夠的時候才被回收,在內存足夠的時候,通常不被回收。

在java.lang.ref包中提供了幾個類:SoftReference類、WeakReference類和PhantomReference類,它們分別代表軟引用、弱引用和虛引用。ReferenceQueue類表示引用隊列,它可以和這三種引用類聯合使用,以便跟蹤Java虛擬機回收所引用的對象的活動。

在Android應用的開發中,為了防止內存溢出,在處理一些佔用內存大而且聲明周期較長的對象時候,可以盡量應用軟引用和弱引用技術。

下面以使用軟引用為例來詳細說明。弱引用的使用方式與軟引用是類似的。

假設我們的應用會用到大量的默認圖片,比如應用中有默認的頭像,默認游戲圖標等等,這些圖片很多地方會用到。如果每次都去讀取圖片,由於讀取文件需要硬體操作,速度較慢,會導致性能較低。所以我們考慮將圖片緩存起來,需要的時候直接從內存中讀取。但是,由於圖片佔用內存空間比較大,緩存很多圖片需要很多的內存,就可能比較容易發生OutOfMemory異常。這時,我們可以考慮使用軟引用技術來避免這個問題發生。

首先定義一個HashMap,保存軟引用對象。

private Map<String, SoftReference<Bitmap>> imageCache = new HashMap<String, SoftReference<Bitmap>>();

再來定義一個方法,保存Bitmap的軟引用到HashMap。

public void addBitmapToCache(String path) {

// 強引用的Bitmap對象

Bitmap bitmap = BitmapFactory.decodeFile(path);

// 軟引用的Bitmap對象

SoftReference<Bitmap> softBitmap = new SoftReference<Bitmap>(bitmap);

// 添加該對象到Map中使其緩存

imageCache.put(path, softBitmap);

}

獲取的時候,可以通過SoftReference的get()方法得到Bitmap對象。

public Bitmap getBitmapByPath(String path) {

// 從緩存中取軟引用的Bitmap對象

SoftReference<Bitmap> softBitmap = imageCache.get(path);

// 判斷是否存在軟引用

if (softBitmap == null) {

return null;

}

// 取出Bitmap對象,如果由於內存不足Bitmap被回收,將取得空

Bitmap bitmap = softBitmap.get();

return bitmap;

}

使用軟引用以後,在OutOfMemory異常發生之前,這些緩存的圖片資源的內存空間可以被釋放掉的,從而避免內存達到上限,避免Crash發生。

需要注意的是,在垃圾回收器對這個Java對象回收前,SoftReference類所提供的get方法會返回Java對象的強引用,一旦垃圾線程回收該Java對象之後,get方法將返回null。所以在獲取軟引用對象的代碼中,一定要判斷是否為null,以免出現NullPointerException異常導致應用崩潰。

經驗分享:

到底什麼時候使用軟引用,什麼時候使用弱引用呢?

個人認為,如果只是想避免OutOfMemory異常的發生,則可以使用軟引用。如果對於應用的性能更在意,想盡快回收一些佔用內存比較大的對象,則可以使用弱引用。

還有就是可以根據對象是否經常使用來判斷。如果該對象可能會經常使用的,就盡量用軟引用。如果該對象不被使用的可能性更大些,就可以用弱引用。

另外,和弱引用功能類似的是WeakHashMap。WeakHashMap對於一個給定的鍵,其映射的存在並不阻止垃圾回收器對該鍵的回收,回收以後,其條目從映射中有效地移除。WeakHashMap使用ReferenceQueue實現的這種機制。

Ⅷ android什麼時候需要線程池

系統提供了AsyncTask,AsyncTask本身就維護一個線程池呢,還有就是Java本身提供的Executors,應用場景的話平時用到網路請求的時候就需要用到線程池,還有就是圖片的緩存的時候也需要用到線程池,比如說listview的item裡面有圖片需要載入,就需要開啟線程池就載入。

Ⅸ Android 開發中,有哪些坑需要注意

在Android library中不能使用switch-case語句訪問資源ID:在Android library中不能使用switch-case語句訪問資源ID的原因分析及解決方案**

不能在Activity沒有完全顯示時顯示PopupWindow和Dialog:popupwindow - Problems creating a Popup Window in Android Activity**

在多進程之間不要用SharedPreferences共享數據,雖然可以(MODE_MULTI_PROCESS),但極不穩定:android - MODE_MULTI_PROCESS for SharedPreferences isn't working**

有些時候不能使用Application的Context,不然會報錯(比如啟動Activity,顯示Dialog等):

同一個應用的JNI代碼,不要輕易換NDK編譯的版本,否則會有很多問題(主要是一些方法實現不一樣,並且高版本對代碼的檢測更嚴格),比如r8沒有問題,但到r9就有問題了,這是個大坑;

Android的JNI代碼中,有返回類型的函數沒有返回值編譯的時候也不會報錯;

當前Activity的onPause方法執行結束後才會執行下一個Activity的onCreate方法,所以在onPause方法中不適合做耗時較長的工作,這會影響到頁面之間的跳轉效率;

謹慎使用Android的透明主題,透明主題會導致很多問題,比如:如果新的Activity採用了透明主題,那麼當前Activity的onStop方法不會被調用;在設置為透明主題的Activity界面按Home鍵時,可能會導致刷屏不幹凈的問題;進入主題為透明主題的界面會有明顯的延時感;

不要在非UI線程中初始化ViewStub,否則會返回null;

公共介面一定要考慮到代碼重入的情況,能設計為單例就盡量用單例;

不要通過Bundle傳遞大塊的數據,否則會報TransactionTooLargeException異常:java - Issue: Passing large data to second Activity**

盡量不要通過Application緩存數據,這不穩定:不要在Android的Application對象中緩存數據!**

盡量不要使用AnimationDrawable,它在初始化的時候就將所有圖片載入到內存中,特別占內存,並且還不能釋放,釋放之後下次進入再次載入時會報錯;

9圖不能通過tinypng壓縮,不然會有問題;

genymotion模擬器快是因為它是基於x86架構的,如果你的應用中用到了so,但沒有x86架構的so,只能放棄使用它;Android Studio的模擬器也一樣;

Eclipse的Android開發環境配置好後不要輕易升級ADT和build tools,不然會浪費你很多時間,還有就是一個workspace中的工程不要太多,不然每次啟動都會很慢;

Android studio每個版本、gradle每個版本差別都比較大(我是這樣認為的),對於jni代碼的編譯建議在Eclipse中進行,如果在Android studio中開發jni會浪費很多時間,主要是編譯腳本的配置比較麻煩;

Eclipse中的Lint太不靠譜,特別是主工程中依賴library的時候,很多提示都是有問題的,建議使用Android Studio的工程清理工具,特別推薦。

AsyncTask默認自己維護一個靜態的線程池,而該線程池只允許同時執行一個線程,也就是說,不管多少個AsyncTask,只要是調用execute()方法,都是共享這個默認進程池的,你的任務必須在之前的任務執行完以後,才能執行。調用AsyncTask的excute方法不能立即執行程序的原因分析及改善方案**

閱讀全文

與android緩存池相關的資料

熱點內容
哪裡有無損音樂app下載 瀏覽:221
單片機如何使用proteus 瀏覽:991
java常用的伺服器 瀏覽:281
集結APP在哪裡下載 瀏覽:800
歐洲cf玩什麼伺服器 瀏覽:529
如何連接另一台電腦上的共享文件夾 瀏覽:681
如何讓桌面文件夾搬家到e盤 瀏覽:73
java自動格式化 瀏覽:619
ipad怎麼查看文件夾大小 瀏覽:583
手工粘土解壓球 瀏覽:552
在線視頻教育源碼 瀏覽:41
快四十學什麼編程 瀏覽:754
gnumakelinux 瀏覽:537
視易峰雲伺服器怎麼改系統 瀏覽:535
javamap取值 瀏覽:768
mac和win磁碟加密軟體 瀏覽:474
蘋果為什麼會連接不到伺服器 瀏覽:726
pdf格式文件如何保存 瀏覽:303
小霸王伺服器tx什麼意思 瀏覽:75
解釋dns命令 瀏覽:584