导航:首页 > 操作系统 > 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缓存池相关的资料

热点内容
进入组策略的命令 浏览:137
python数据结构和内存 浏览:25
python软件功能简介 浏览:784
外国程序员一般多少岁退休 浏览:917
怎么看linux和时间服务器 浏览:680
程序员搞笑花名 浏览:501
dota2怎么设置国服服务器地址 浏览:212
单片机高电平驱动 浏览:115
ios多选文件夹 浏览:909
加强行车调度命令管理 浏览:243
服务器已禁用什么意思 浏览:150
部队命令回复 浏览:755
神奇宝贝服务器地图怎么设置 浏览:382
加密算法输出固定长度 浏览:862
程序员去重庆还是武汉 浏览:121
服务器如何撤销网页登录限制 浏览:980
微信公众平台php开发视频教程 浏览:628
怎么看苹果授权绑定的app 浏览:255
压缩机单级压缩比 浏览:380
linux测试php 浏览:971