1、RecycleView与ListView的区别:
- RecycleView的基本使用
- ListView 和 RecyclerView 复用机制区别
- RecycleView在布局的优点:可以支持横向滚动,支持网格布局、线性布局、瀑布流布局
- RecyclerView 复用 Item 的工作 Google 全帮你搞定,不再需要像 ListView 那样自己调用 setTag
- 在 ListView 的设计中,存在着 HeaderView 和 FooterView 两种类型的视图,并且系统也提供了相应的 API 来让我们设置。使用 HeaderView 和 FooterView 的好处在于,当我们指向在 ListView 的头部或者底部添加一个 View 的时候(例如:添加一个下拉刷新视图,底部加载更多视图),我们可以不用影响到 Adapter 的编写,使用起来相当方便。而到了 RecyclerView 中,没有类似 addFooterView 、 addFooterView 这种 API
- 在 ListView 中,说到刷新会记得 notifyDataSetChanged() 。在更新了 ListView 的数据源后,需要通过 Adapter 的 notifyDataSetChanged 来通知视图更新变化,这样做比较的好处就是调用简单,坏处就是它会重绘每个 Item。但是listView并没有提供局部刷新的方法,自定义(在自定义的adapter类中添加方法):
public void updateItemView(ListView listView, int position) {
//换算成 Item View 在 ViewGroup 中的 index
int index = position - listView.getFirstVisiblePosition();
if (index >= 0 && index < listView.getChildCount()) {
//更新数据
AuthorInfo authorInfo = mAuthorInfoList.get(position);
authorInfo.setNickName("Google Android");
authorInfo.setMotto("My name is Android .");
authorInfo.setPortrait(R.mipmap.ic_launcher);
//更新单个Item
View itemView = listView.getChildAt(index);
getView(position, itemView, listView);
}
}
- RecycleView.adapter则提供了 notifyItemChanged 用于更新单个 Item View 的刷新,我们可以省去自己写局部更新的工作。
- 刷新动画效果:listView没有,RecycleView有
- item监听事件:ListView 为我们准备了几个专门用于监听 Item 的回调接口,如单击、长按、选中某个 Item 等,如 setOnItemClickListener ,在我们不添加 HeaderView 和 FooterView 的时候,我们可以通过回调参数中的 position 去拿到数据源列表中对应 Item 的数据。但是,添加了 HeaderView 和 FooterView 之后就不一样了,ListView 会把 HeaderView 和 FooterView 算入 position 内
- RecyclerView ,它并没有像 ListView 提供太多关于 Item 的某种事件监听,唯一的就是 addOnItemTouchListener
3、kotlin的拓展方法
- Kotlin语言支持对现有的类进行扩展。 所谓扩展,就是在不使用继承的情况下,对已有的类新增方法、属性等操作,扩展不会破坏现有的类,仅仅在使用的时候进行动态添加。原则: 扩展优于继承
- 例:给User类添加Print方法:
class User(var name:String)
// 给user类增加方法
fun User.Print(){
print("用户名 $name")
}
//调用
fun main(arg:Array<String>){
var user = User("Runoob")
user.Print()
}
伴生对象:
- companion object { }
- 在类加载时就会运行伴生对象的代码块,其作用相当于Java里面的static { ... }代码块
- java静态成员的优点:
1、这样就可以使类中的某些变量和方法与该类绑定,而不是与某一对象绑定,增加其生命周期。
2、这样就可以使该类的所有对象共享这个变量和方法,无需为每个对象分配该变量的资源,充分节省资源。 - Kotlin中没有静态变量,So它使用了伴生对象来模仿Java中静态变量的作用。伴生对象也是在类加载阶段初始化,同样生命周期与该类的生命周期一致且也可以直接通过类名.(attribute,method)来调用。该类的多个对象共享该伴生对象。
kotlin相对于Java有什么优缺点:
- 在Kotlin语言中,类终于不再是一等公民。Kotlin语言开始支持面向过程编程,Kotlin语言中可以声明全局函数、内联函数等,还支持函数嵌套,使用函数作为方法参数等操作。对于一些简单的操作,新建一个类去处理,的确有时候是一个让人头疼的问题,Kotlin语言让我们摆脱了这一尴尬的现状。
- 数据类:我们常常要不断写一些Model类,不断地使用开发工具生成set/get方法。Data Class就是为简化这个操作而生的,数据类会自动生成set/get方法,而不用显式生成set/get方法
- Kotlin和Java语言可以实现完全地互同调用,Kotlin最终也会编译成Java字节码。
- 完全兼容Java
- Null safe(空指针安全)
- 支持lambda表达式(比Java8更好)
- 支持扩展
- 体验一致的开发工具链
- 相对于java更简洁
面向对象六大原则:
-
单一职责原则:单一职责原则的定义是就一个类而言,应该仅有一个引起他变化的原因。也就是说一个类应该只负责一件事情。单一职责原则的好处如下:
可以降低类的复杂度,一个类只负责一项职责,这样逻辑也简单很多
提高类的可读性,和系统的维护性,因为不会有其他奇怪的方法来干扰我们理解这个类的含义
当发生变化的时候,能将变化的影响降到最小,因为只会在这个类中做出修改。 -
开闭原则的定义是软件中的对象(类,模块,函数等)应该对于扩展是开放的,但是对于修改是关闭的。当需求发生改变的时候,我们需要对代码进行修改,这个时候我们应该尽量去扩展原来的代码,而不是去修改原来的代码,因为这样可能会引起更多的问题。
-
里氏替换原则:所有引用基类的地方必须能够透明地使用其子类的对象。子类可以去扩展父类的功能,但是不能改变父类原有的功能。
里氏替换原则之所以这样要求是因为继承有很多缺点,他虽然是复用代码的一种方法,但同时继承在一定程度上违反了封装。父类的属性和方法对子类都是透明的,子类可以随意修改父类的成员。这也导致了,如果需求变更,子类对父类的方法进行一些复写的时候,其他的子类无法正常工作。所以里氏替换法则被提出来。 -
依赖倒置原则:依赖倒置原则指的是一种特殊的解耦方式,使得高层次的模块不应该依赖于低层次的模块的实现细节的目的,依赖模块被颠倒了。这也是一个让人难懂的定义,他可以简单来说就是:
1、 高层模块不应该依赖底层模块,两者都应该依赖其抽象
2、抽象不应该依赖细节
3、 细节应该依赖抽象
在Java 中抽象指的是接口或者抽象类,两者皆不能实例化。而细节就是实现类,也就是实现了接口或者继承了抽象类的类。他是可以被实例化的。高层模块指的是调用端,底层模块是具体的实现类。在Java中,依赖倒置原则是指模块间的依赖是通过抽象来发生的,实现类之间不发生直接的依赖关系,其依赖关系是通过接口是来实现的。这就是俗称的面向接口编程。
- 接口隔离原则:客户端不应该依赖他不需要的接口。换一种说法就是类间的依赖关系应该建立在最小的接口上。例如,当类A要实现接口yk时,接口yk有5个方法,但是A用到的只有其中三个,这时候就可以对接口yk进行拆分,将要用到的三个分为一类。
- 迪米特原则:一个对象应该对其他对象保持最小的了解。 因为类与类之间的关系越密切,耦合度越大,当一个类发生改变时,对另一个类的影响也越大,所以这也是我们提倡的软件编程的总的原则:高内聚,低耦合。只与直接的朋友通信。首先来解释一下什么是直接的朋友:每个对象都会与其他对象有耦合关系,只要两个对象之间有耦合关系,我们就说这两个对象之间是朋友关系。耦合的方式很多:依赖、关联、组合、聚合等。其中,我们称出现在成员变量、方法参数、方法返回值中的类为直接的朋友,而出现在局部变量中的类则不是直接的朋友。也就是说,陌生的类最好不要作为局部变量的形式出现在类的内部。
例子:这里我们可以用一个现实生活中的例子来讲解一下。比如我们需要一张CD,我们可能去音像店去问老板有没有我们需要的那张CD,老板说现在没有,等有的时候你们来拿就行了。在这里我们不需要关心老板是从哪里,怎么获得的那张CD,我们只和老板(直接朋友)沟通,至于老板从他的朋友那里通过何种条件得到的CD,我们不关心,我们不和老板的朋友(陌生人)进行通信,这个就是迪米特的一个应用。说白了,就是一种中介的方式。我们通过老板这个中介来和真正提供CD的人发生联系。
5、Android有哪几种类型的进程
-
前台进程
这个进程是最重要的,是最后被销毁的。前台进程是目前正在屏幕上显示的进程和一些系统进程,也就是和用户正在交互的进程。例如,我正在使用qq跟别人聊天,在我的Android手机上这个进程就应该是前台进程。 -
可见进程
可见进程指部分程序界面能够被用户看见,却不在前台与用户交互的进程。例如,我们在一个界面上弹出一个对话框(该对话框是一个新的Activity),那么在对话框后面的原界面是可见的,但是并没有与用户进行交互,那么原界面就是可见进程。 -
服务进程
服务进程是通过 startService() 方法启动的进程,但不属于前台进程和可见进程。例如,在后台播放音乐或者在后台下载就是服务进程。 -
后台进程
后台进程指的是目前对用户不可见的进程。例如我正在使用qq和别人聊天,这个时候qq是前台进程,但是当我点击Home键让qq界面消失的时候,这个时候它就转换成了后台进程。当内存不够的时候,可能会将后台进程回收。 -
空进程
空进程指的是在这些进程内部,没有任何东西在运行。保留这种进程的的唯一目的是用作缓存,以缩短该应用下次在其中运行组件所需的启动时间。 -
它们的回收顺序从先到后分别是:空进程,后台进程,服务进程,可见进程,前台进程。
6、server、activity的区别和运用场景:
- 关于android编程中service和activity的区别
- 绝大部分情况下,Service的作用是用来“执行”后台的、耗时的、重要的任务,三者缺一不可,而最重要的原因是第三点:要执行重要的任务。当一个进程启动了Service后,进程的优先级变高了,系统除非在非常极端的情况下,不会杀掉该进程,Activity不具备这样的特性。
- Activity和Service的生命周期不一样,Activity处在哪个生命周期是由系统控制的,service是由程序控制的,service不能自己启动,而且service不与用户交互。
- service可以运行在后台,但是activity不行
service就是没界面关联的纯逻辑Activity,然后,service能够有两种状态,1.程序退出后在后台运行本服务,2.程序运行时在后台执行某些操作。 - 除了楼上所说的,service的另外一种重要的用途是实现跨进程调用,其中Binder的概念比较重要,AIDL也与Binder有关,而Acitity并不处理跨进程调用的工作。
- Service后台运行,类似服务,和Activety是一个级别类似,但是自己无法运行,需要Activity或者其他对象调用。
- 如果是startService ,关闭了 调用service的线程,service是不会被关闭的,如果是bindService,Service就和调用bindService的进程同生共死了,也就是说当调用bindService的进程死了,那么它bind的Service也要跟着被结束
- IntentService解析:https://www.jianshu.com/p/af62781fefba
- Service和其他的组件一样也在应用的主线程中运行,如果服务组件执行比较耗时的操作就会导致主线程阻塞或者假死
8、view和layout的关系:
-
View是界面显示的基本单元,会draw()到Canvas上。ViewGroup继承View,是个容器,内部有View数组;所有Layout(如LinearLayout,FrameLayout)也都继承ViewGroup;
9、Java虚拟机与进程的关系:
- Java编写的程序都运行在在Java虚拟机(JVM)中。运行一个java程序,就会启动一个JVM进程。在同一个JVM进程中,有且只有一个进程,就是它自己。在这个JVM环境中,所有程序代码的运行都是以线程来运行的。JVM找到程序程序的入口点main(),然后运行main()方法,这样就产生了一个线程,这个线程称之为主线程。当main方法结束后,主线程运行完成。JVM进程也随即退出
- JVM本质就是一个进程
- 整个内存空间主要被分成两个部分:内核内存(Kernel space)、用户内存(User space)。用户内存是提供给各个进程主要空间,Linux给各个进程提供相同的虚拟内存空间;这使得进程之间相互独立,互不干扰。给每一个进程一定虚拟内存空间,而只有当虚拟内存实 际被使用时,才分配物理内存。
- JVM 与 Linux 的内存关系详解 - 知乎 (zhihu.com)
10、堆和栈的关系:
-
void f() { int* p=new int[5]; }
这条短短的一句话就包含了堆与栈,看到new,我们首先就应该想到,我们分配了一块堆内存,那么指针p呢?他分配的是一块栈内存,所以这句话的意思就是:在 栈 内存中存放了一个指向一块堆内存的指针p。在程序会先确定在堆中分配内存的大小,然后调用operator new分配内存,然后返回这块内存的首地址,放入栈中。 -
堆栈空间分配
栈(操作系统):由操作系统自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
堆(操作系统): 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收,分配方式倒是类似于链表 -
堆栈缓存方式
栈使用的是一级缓存, 他们通常都是被调用时处于存储空间中,调用完毕立即释放。
堆则是存放在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定(并不是一旦成为孤儿对象就能被回收)。所以调用这些对象的速度要相对来得低一些。 -
堆和栈相比:堆由于大量new/delete的使用,容易造成大量的内存碎片;由于没有专门的系统支持,效率很低;由于可能引发用户态和核心态的切换,内存的申请,代价变得更加昂贵。所以栈在程序中是应用最广泛的,就算是函数的调用也利用栈去完成,函数调用过程中的参数,返回地址,EBP和局部变量都采用栈的方式存放。
-
对于堆来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于栈来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
-
分配方式:堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由编译器进行释放,无需我们手工实现。(所以栈的分配效率高于堆)
-
碎片问题:对于堆来讲,频繁的new/delete势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题,因为栈是先进后出的队列,他们是如此的一一对应,以至于永远都不可能有一个内存块从栈中间弹出,在他弹出之前,在他上面的后进的栈内容已经被弹出。
-
管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制,容易产生memory leak。
-
空间大小:一般来讲在32位系统下,堆内存可以达到4G的空间,从这个角度来看堆内存几乎是没有什么限制的。但是对于栈来讲,一般都是有一定的空间大小的,例如,在VC6下面,默认的栈空间大小是1M(好像是,记不清楚了)。
11、你学过iOS开发,那你简单说一下iOS和Android引用计数的区别
12、说一下栈溢出,说一下什么情况下会遇到这样的错误,为什么会遇到这样的错误:
-
缓冲区溢出:计算机程序一般都会使用到一些内存,这些内存或是程序内部使用,或是存放用户的输入数据,这样的内存一般称作缓冲区。溢出是指盛放的东西超出容器容量而溢出来了,在计算机程序中,就是数据使用到了被分配内存空间之外的内存空间。而缓冲区溢出,简单的说就是计算机对接收的输入数据没有进行有效的检测(理想的情况是程序检查数据长度并不允许输入超过缓冲区长度的字符),向缓冲区内填充数据时超过了缓冲区本身的容量,而导致数据溢出到被分配空间之外的内存空间,使得溢出的数据覆盖了其他内存空间的数据。
-
缓冲区溢出攻击:通过往程序的缓冲区写超出其长度的内容,造成缓冲区的溢出,从而破坏程序的堆栈,造成程序崩溃或使程序转而执行其它指令,以达到攻击的目的。造成缓冲区溢出的原因是程序中没有仔细检查用户输入的参数。而缓冲区溢出中,最为危险的是堆栈溢出,因为入侵者可以利用堆栈溢出,在函数返回时改变返回程序的地址,让其跳转到任意地址,带来的危害一种是程序崩溃导致拒绝服务,另外一种就是跳转并且执行一段恶意代码,比如得到shell,然后为所欲为。
-
堆是一种树结构,准确地说是一个完全二叉树。
-
当一个可执行程序被装入到内存时,主要包括两个部分 :代码和数据。代码会被装入到内存中的代码区,数据区又由 3 部分组成 :①全局变量:根据其是否有初始值,被装入到内存中的未初始化数据区和初始化数据区;②局部变量:在函数调用发生时存放在栈中;③动态内存空间:在程序运行时申请的动态内存空间存放在堆中
-
溢出原因:
堆栈尺寸设置过小
递归层次太深或函数调用层次过深导致堆栈溢出
动态申请空间使用之后没有释放
13、栈与线程的关系:
-
堆:是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
-
栈: 是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe 的。每个函数都有自己的栈,栈被用来在函数之间传递参数。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
-
栈是线程私有的,每个线程都是自己的栈,每个线程中的每个方法在执行的同时会创建一个栈帧用于存局部变量表、操作数栈、动态链接、方法返回地址等信息。每一个方法从调用到执行完毕的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的过程。其中局部变量表,存放基本类型(boolean、byte、char、short、int、float)、对象的引用等等,对象的引用不是对象实例本身,而是指向对象实例的一个指针。
-
堆是线程共享的,所有的对象的实例和数组都存放在堆中,任何线程都可以访问。Java的垃圾自动回收机制就是运用这个区域的。
-
方法区也是线程共享的,用于存放类信息(包括类的名称、方法信息、字段信息)、常量、静态变量以及即时编译器编译后的代码等等。
14、你觉得你在平时的实践过程中或是在学习过程中有什么做的比较不错的,可以分享一下吗?
1、我有将自己所学习过的东西用简书进行记录的习惯,一方面是为了分享,但在书写的过程中,也加深了对知识点的巩固和理解。同时也方便了以后的复习。我觉得将所学的知识、说写的代码、写代码遇到的问题进行记录是很有必要的。
2、
15、你在GitHub上传过什么
16、你在学校担任过什么职务或者做过什么比较有意义的事,你从中收获了什么?
1、大一大二参加过学校的社团(不是学生会)。在大一时还是个普通会员,每次做事都是学长具体安排,去做就行了。但是到大二就不是这样了,但大二时是社团社团外联部的部长,做的事不再是某个具体的任务,而是要思考一件事要怎么完成、分几个步骤去完成。比如拉赞助:在大一时收到的任务是什么时间到什么地点去找谁获取赞助;但是到了大二,思考的是该向谁获取赞助,以什么样的方式获取赞助,具体的执行有其他人完成。我觉得这跟员工在公司中做事方式是相似的:员工只用负责某件具体的事,而公司领导则赋值公司的走向、战略。
2、在大三时学校老师面向大一的新生举办了一个Android开发培训班,我在那个班上担任助教,帮助他们解决编程过程中遇到的问题:开发工具问题、代码问题、知识点不理解的问题等。在帮助他们解决问题的过程中,我自己也得到了一定的锻炼,表达能力:我觉得很简单的问题,解释给他们听,他们却觉得很难,所以我的转换思路,站在他们的角度去思考问题,然后慢慢的接收给他们听。思维能力:虽然题目现在还在学C语言,问得问题比较简单,但有时候也会有些难题或者不知名的一些错误,我的慢慢去打断点、打印调试代码,找到错误所在,在这过程中我的编程思维和解决问题的能力也得到了一定的提升。
19、组合(引用)跟继承的使用场景区别:
-
组合是通过对现有对象进行拼装即组合产生新的具有更复杂的功能。
-
继承与组合的区别与联系:继承与组合都是面向对象中代码复用的方式。在继承中:父类的内部细节对子类可见,其代码属于白盒式的复用;而组合中,对象之间的内部细节不可见,其代码属于黑盒式复用。继承在编码过程中就要指定具体的父类,其关系在编译期就确定,而组合的关系一般在运行时确定。
- 继承的优点:
支持扩展,通过继承父类实现,但会使系统结构较复杂。易于修改被复用的代码- 继承的缺点:
代码白盒复用,父类的实现细节暴露给子类,破坏了封装性
当父类的实现代码修改时,可能使得子类也不得不修改,增加维护难度。
子类缺乏独立性,依赖于父类,耦合度较高
不支持动态拓展,在编译期就决定了父类
- 组合的优点:
代码黑盒复用,被包括的对象内部实现细节对外不可见,封装性好。
整体类与局部类之间松耦合,相互独立。
支持扩展
每个类只专注于一项任务
支持动态扩展,可在运行时根据具体对象选择不同类型的组合对象(扩展性比继承好)- 组合的缺点:
创建整体类对象时,需要创建所有局部类对象。导致系统对象很多。
- 什么情况下使用继承,什么情况下使用组合?
从前面的分析看,组合的优点明显多于继承,再加上java中仅支持单继承,所以:
除非两个类之间是is-a的关系,否则尽量使用组合。
java--依赖、关联、聚合和组合之间区别的理解
-
依赖(Dependency)关系是类与类之间的联接。依赖关系表示一个类依赖于另一个类的定义。例如,一个人(Person)可以买车(car)和房子(House),Person类依赖于Car类和House类的定义,因为Person类引用了Car和House。与关联不同的是,Person类里并没有Car和House类型的属性,Car和House的实例是以参量的方式传入到buy()方法中去的。一般而言,依赖关系在Java语言中体现为局域变量、方法的形参,或者对静态方法的调用。
-
关联(Association)关系是类与类之间的联接,它使一个类知道另一个类的属性和方法。关联可以是双向的,也可以是单向的。在Java语言中,关联关系一般使用成员变量来实现。
-
聚合(Aggregation) 关系是关联关系的一种,是强的关联关系。聚合是整体和个体之间的关系。例如,汽车类与引擎类、轮胎类,以及其它的零件类之间的关系便整体和个体的关系。与关联关系一样,聚合关系也是通过实例变量实现的。但是关联关系所涉及的两个类是处在同一层次上的,而在聚合关系中,两个类是处在不平等层次上的,一个代表整体,另一个代表部分。
-
组合(Composition) 关系是关联关系的一种,是比聚合关系强的关系。它要求普通的聚合关系中代表整体的对象负责代表部分对象的生命周期,组合关系是不能共享的。代表整体的对象需要负责保持部分对象和存活,在一些情况下将负责代表部分的对象湮灭掉。代表整体的对象可以将代表部分的对象传递给另一个对象,由后者负责此对象的生命周期。换言之,代表部分的对象在每一个时刻只能与一个对象发生组合关系,由后者排他地负责生命周期。部分和整体的生命周期一样。
缓存区:
-
缓冲区(buffer),它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区,缓冲区是具有一定大小限制的。
-
缓冲区根据其对应的输入设备、输出设备,分为输入缓冲区和输出缓冲区。
-
高速设备与低速设备的不匹配,势必会让高速设备花时间等待低速设备,我们可以在这两者之间设立一个缓冲区。可以解除两者的制约关系,数据可以直接送往缓冲区,高速设备不用再等待低速设备,提高了计算机的效率。
-
缓存区的另一个作用:可以减少数据的读写次数,如果每次数据只传输一点数据,就需要传送很多次,这样会浪费很多时间,因为开始读写与终止读写所需要的时间很长,如果将数据送往缓冲区,待缓冲区满后再进行传送会大大减少读写次数,这样就可以节省很多时间。
-
缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。
-
缓存:Cache就是用来解决CPU与内存之间速度不匹配的问题,避免内存与辅助内存频繁存取数据,这样就提高了系统的执行效率。
-
缓存和缓冲的区别:
1、Buffer的核心作用是用来缓冲,缓和冲击。比如你每秒要写100次硬盘,对系统冲击很大,浪费了大量时间在忙着处理开始写和结束写这两件事嘛。用个buffer暂存起来,变成每10秒写一次硬盘,对系统的冲击就很小,写入效率高了,日子过得爽了。极大缓和了冲击。
2、Cache的核心作用是加快取用的速度。比如你一个很复杂的计算做完了,下次还要用结果,就把结果放手边一个好拿的地方存着,下次不用再算了。加快了数据取用的速度。
3、简单来说就是buffer偏重于写,而cache偏重于读。
网友评论