设计模式
摘要:什么是设计模式
设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。
这里列举了三种最基本的设计模式:
- 创建模式,提供实例化的方法,为适合的状况提供相应的对象创建方法
- 结构化模式,通常用来处理实体之间的关系,使得这些实体能够更好地协同工作
- 行为模式,用于在不同的实体间进行同学,为实体之间的同学提供更容易,更灵活的通信方法
设计模式是经过总结、优化的,对我们经常会碰到的一些编程问题的可重用解决方案。
这里列举了三种最基本的设计模式:
有2种形式,一种是limit后面带一个值,另一种是带2个值。
select prod_name from products limit 5
;将返回从第1行开始的前5条数据。
select prod_name from products limit 5,5
; 表示返回从行5开始的5行数据。第一个数为开始位置,第二个数为要检索的行数。
1 | select hire_date from employees |
offset
:去掉几行元素。上面的意思就是掉排名倒数第一第二的时间,然后limit 表示取第一条记录,取倒数第三
“Group By”从字面意义上理解就是根据“By”指定的规则对数据进行分组,所谓的分组就是将一个“数据集”划分成若干个“小区域”,然后针对若干个“小区域”进行数据处理。
1 | INSERT into actor(actor_id, first_name, last_name, last_update) |
本题考查的是replace函数,其中包含三个参数,第一个参数为该字段的名称,第二参数为该字段的需要被修改值,第三个参数为该字段修改后的值。
1 | UPDATE titles_test |
UPDATE和REPLACE基本类似,但是它们之间有两点不同。
首先查重,
- 当没有找到匹配记录(不存在重复记录)时:
UPDATE什么都不做,
REPLACE会做insert动作。- 当找到匹配记录(存在重复记录)时:
UPDATE可以更新记录的一部分字段。
REPLACE将已存在记录彻底删除(DELETE),再插入新的记录(INSERT)。也就是说,将所有的字段都更新为新记录的字段了
round(聚合函数,小数位数),可以精确到小数点后多少位
<>、!=、 is not
都是不相等
MySQL中不允许在子查询的同时删除表数据(不能一边查一边把查的表删了)
给你一个长度为 $n$ 的字符串数组 $strs$,编写一个函数来查找字符串数组中的最长公共前缀,返回这个公共前缀。
先得到最短的字符串,然后用最短的字符串去一一比较
1 | class Solution: |
对于一个字符串,请设计一个高效算法,计算其中最长回文子串的长度。
给定字符串A以及它的长度n,请返回最长回文子串的长度。
定义 dp[i][j]
表示 A[i:j]
是否为回文串。
外循环从后向前遍历,i ->[6 0]
内循环从 i
开始向后遍历,直接结束。
每轮内循环的第一次循环可以解决 单个字符的回文串。
每次循环由外向内检测字串是否为回文串。
1 | class Solution: |
给定两个字符串str1和str2,输出两个字符串的最长公共子串
题目保证str1和str2的最长公共子串存在且唯一。
1 | class Solution: |
参考评论区:
【数据结构和算法】动态规划解最长公共子串_牛客博客 (nowcoder.net)
注意这题求的是最长公共子串,不是最长公共子序列,子序列可以是不连续的,但子串一定是连续的。
定义 dp[i][j]
表示字符串 str1
中的第 i
个字符和 str2
中 第 j
个字符为最后一个元素所构成的最长公共字串。
如果要求 dp[i][j]
,也就是 str1
的第 i
个字符和str2
的第j
个字符为最后一个元素所构成的最长公共字串,我们首先需要判断这两个字符是否相等。
如果不相等,那么他们就不能构成公共字串,也就是
dp[i][j]=0
如果相等,我们还需要计算前面相等字符的个数,其实就是 dp[i-1][j-1]
,所有
dp[i][j]=dp[i-1][j-1]+1
其重点是,以i,j分别是str1,str2的结束字符串,当前的结尾字符记录,会在前一个字符记录上进行迭代,同时在迭代过程中记录字串长度,并记住结束位置
1 | class Solution: |
1 | maxLastIndex = 0 # |
其分别为Activity、Service、Content Provider、Broadcast receiver。
(1)一个Activity通常就是一个单独的屏幕(窗口)。
(2)Activity之间通过Intent进行通信。
(3)android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。
service用于在后台完成用户指定的操作。service分为两种:
started
(启动):当应用程序组件(如activity
)调用startService()
方法启动服务时,服务处于started状态。bound
(绑定):当应用程序组件调用bindService()
方法绑定到服务时,服务处于bound状态。startService()
与bindService()
区别:
started service
(启动服务)是由其他组件调用startService()方法启动的,这导致服务的onStartCommand()
方法被调用。当服务是started
状态时,其生命周期与启动它的组件无关,并且可以在后台无限期运行,即使启动服务的组件已经被销毁。因此,服务需要在完成任务后调用stopSelf()方法停止,或者由其他组件调用stopService()
方法停止。bindService()
方法启用服务,调用者与服务绑定在了一起,调用者一旦退出,服务也就终止,大有“不求同时生,必须同时死”的特点。开发人员需要在应用程序配置文件中声明全部的service
,使用<service></service>
标签。
Service通常位于后台运行,它一般不需要与用户交互,因此Service组件没有图形用户界面。Service组件需要继承Service基类。Service组件通常用于为其他组件提供后台服务或监控其他组件的运行状态。
Content Provider
使一个应用程序的指定数据集提供给其他应用程序。其他应用可以通过ContentResolver
类从该内容提供者中获取或存入数据。ContentProvider
实现数据共享。ContentProvider
用于保存和获取数据,并使其对所有应用程序可见。这是不同应用程序间共享数据的唯一方式,因为android没有提供所有应用共同访问的公共存储区。ContentProvider
类的对象,大多数是通过ContentResolver
对象实现对ContentProvider
的操作。ContentProvider
使用URI来唯一标识其数据集,这里的URI以content://
作为前缀,表示该数据由ContentProvider
来管理。4大基本组件都需要注册才能使用,每个Activity、service、Content Provider都需要在AndroidManifest文件中进行配置。
AndroidManifest文件中未进行声明的activity、服务以及内容提供者将不为系统所见,从而也就不可用。
而broadcast receiver广播接收者的注册分静态注册(在AndroidManifest文件中进行配置)和通过代码动态创建并以调用Context.registerReceiver()的方式注册至系统。
需要注意的是在AndroidManifest文件中进行配置的广播接收者会随系统的启动而一直处于活跃状态,只要接收到感兴趣的广播就会触发(即使程序未运行)。
内容提供者的激活:当接收到ContentResolver发出的请求后,内容提供者被激活。
而其它三种组件activity
、服务
和广播接收器
被一种叫做intent的异步消息所激活。
内容提供者仅在响应ContentResolver提出请求的时候激活。
而一个广播接收器仅在响应广播信息的时候激活。所以,没有必要去显式的关闭这些组件。
Activity关闭:可以通过调用它的finish()方法来关闭一个activity。
服务关闭:对于通过startService()方法启动的服务要调用Context.stopService()方法关闭服务,使用bindService()方法启动的服务要调用Contex.unbindService()方法关闭服务。
声明Android程序布局有两种方式:
可以使用任何一种声明界面布局的方式,也可以同时使用两种方式。
使用XML文件声明有以下3个特点:
六大界面布局方式包括:
LinearLayout容器中的组件一个挨一个排列,通过控制android:orientation属性,可控制各组件是横向排列还是纵向排列。
XML属性 | 相关方法 | 说明 |
---|---|---|
android:gravity | setGravity(int) | 设置布局管理器内组件的对齐方式 |
android:orientation | setOrientation(int) | 设置布局管理器内组件的排列方式,可以设置为horizontal、vertical两个值之一 |
TableLayout继承自Linearout,本质上仍然是线性布局管理器。表格布局采用行、列的形式来管理UI组件,并不需要明确地声明包含多少行、多少列,而是通过添加TableRow、其他组件来控制表格的行数和列数。
每向TableLayout中添加一个TableRow就代表一行;
每向TableRow中添加一个一个子组件就表示一列;
如果直接向TableLayout添加组件,那么该组件将直接占用一行;
在表格布局中,可以为单元格设置如下三种行为方式:
Shrinkable
:该列的所有单元格的宽度可以被收缩,以保证该表格能适应父容器的宽度;Strentchable
:该列所有单元格的宽度可以被拉伸,以保证组件能完全填满表格空余空间;Collapsed
:如果该列被设置为Collapsed
,那么该列的所有单元格会被隐藏;FrameLayout直接继承自ViewGroup组件。帧布局为每个加入其中的组件创建一个空白的区域(称为一帧),每个子组件占据一帧,这些帧会根据gravity属性执行自动对齐。
一个元素相对另一个元素
它把整个容器划分为rows × columns个网格,每个网格可以放置一个组件。性能及功能都要比tablelayout好,比如GridLayout布局中的单元格可以跨越多行,而tablelayout则不行,此外,其渲染速度也比tablelayout要快。
即Android不提供任何布局控制,而是由开发人员自己通过X坐标、Y坐标来控制组件的位置。每个组件都可指定如下两个XML属性:
绝对布局已经过时,不应使用或少使用。
首先得明确,界面布局类型的嵌套越多越深越复杂,会使布局实例化变慢,使Activity的展开时间延长。建议尽量减少布局嵌套,尽量减少创建View对象的数量。
减少布局层次,可考虑用RelativeLayout来代替LinearLayout。通过Relative的相对其他元素的位置来布局,可减少块状嵌套;
另一种减少布局层次的技巧是使用 <merge />
标签来合并布局;
重用布局。Android支持在XML中使用 <include />
标签, <include />
通过指定android:layout
属性来指定要包含的另一个XML布局。
如:
1 | <include android:id="@+id/id1" android:layout="@layout/mylayout"> |
在Android中,可供选择的存储方式有:
Android提供用来存储一些简单的配置信息的一种机制,例如,一些默认欢迎语、登录的用户名和密码等。其以键值对的方式存储,使得我们可以很方便的读取和存入。
SharedPreferences是以XML的格式以文件的方式自动保存的,在DDMS中的File Explorer中展开到/data/data/<package
name>/shared_prefs下,以上面这个为例,可以看到一个叫做SETTING_Infos.xml的文件
注意:Preferences只能在同一个包内使用,不能在不同的包之间使用。
在Android中,其提供了openFileInput
和 openFileOupu
方法读取设备上的文件,下面看个例子代码,具体如下所示:
1 | String FILE_NAME = "tempfile.tmp"; //确定要操作文件的文件名 |
上述代码中两个方法只支持读取该应用目录下的文件,读取非其自身目录下的文件将会抛出异常。需要提醒的是,如果调用
FileOutputStream
时指定的文件不存在,Android
会自动创建它。另外,在默认情况下,写入的时候会覆盖原文件内容,如果想把
新写入的内容附加到原文件内容后,则可以指定其模式为Context.MODE_APPEND
。
SQLite是Android所带的一个标准的数据库,它支持SQL语句,它是一个轻量级的嵌入式数据库。
1 | /* |
1.什么是ContentProvider
数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据。难道两个程序之间就没有办法对于数据进行交换?解决这个问题主要靠ContentProvider。
一个Content Provider类实现了一组标准的方法接口,从而能够让其他的应用保存或读取此Content Provider的各种数据类型。也就是说,一个程序可以通过实现一个Content Provider的抽象接口将自己的数据暴露出去。外界根本看不到,也不用看到这个应用暴露的数据在应用当中是如何存储的,或者是用数据库存储还是用文件存储,还是通过网上获得,这些一切都不重要,重要的是外界可以通过这一套标准及统一的接口和程序里的数据打交道,可以读取程序的数据,也可以删除程序的数据,当然,中间也会涉及一些权限的问题。
2. 什么是ContentResolver
外界的程序通过ContentResolver接口可以访问ContentProvider提供的数据,在Activity当中通过getContentResolver()可以得到当前应用的ContentResolver实例。
3. ContentProvider和ContentResolver中用到的Uri
在ContentProvider和ContentResolver当中用到了Uri的形式通常有两种,一种是指定全部数据,另一种是指定某个ID的数据。
content://contacts/people/
这个Uri指定的就是全部的联系人数据。
content://contacts/people/1
这个Uri指定的是ID为1的联系人的数据。
pass
https://blog.csdn.net/shenggaofei/article/details/52450668
各生命周期状态说明
方法 | 描述 | 用途(以当前界面播放视频为例) | 下一个方法 |
---|---|---|---|
onCreate() | 当Activity第一次创建时调用。该方法(如果有)会提供给你一个包含之前活动的冻结状态信息bundle包。 | 进行一系列初始化操作,如:创建View,加载视频数据等。 | onStart() |
onRestart() | 当Activity被停止后调用,在重新开始之前 | 当活动停止后重新启动该活动时调用(不常用),针对停止后重启操作。 | onStart() |
onStart() | 当Activity被展示在用户眼前时调用。如果活动出现在前台紧接着是onResume(),如果活动直接隐藏则紧接着是onStop()。 | 该方法也不常用。 | onResume() or onStop() |
onResume() | 当Activity将开始与用户进行交互时调用。在这个时间点你的活动将会在活动堆栈的顶端,用户输入将会访问它。 | 暂停后恢复我们会在该方法中进行一些操作,例如视频继续播放。 | onPause() |
onPause() | 当系统将要恢复一个之前的活动。这是一个有代表性的常常用于提交未被存储的改动信息为持久数据,停止动画和消耗CPU的东西等。实现该方法必须要特别的迅速,因为在此方法返回之前,下一个活动将不会恢复。如果活动将返回到前台则接下来调用onResume(),如果要隐藏到用户看不见的地方时,则调用onStop() | 该方法十分重要,用来做信息持久化存储操作以及停止消耗CPU资源操作,如记录视频播放进度时间,以及暂停视频播放操作等。 | onResume or onStop() |
onStop() | 当另一个活动被恢复且完全覆盖该活动,而该Activity将不在展示给用户时调用。这种情况将发生在一个新的活动将被开始,一个退出的活动将被恢复,又或者该活动将要被销毁。如果该活动将恢复与用户交互则调用onRestart(),如果该活动将被销毁则调用onDestory()。 | 界面将会隐藏或销毁,做一些重要信息或未被存储的信息的存储操作。但也不要太耗时。如存储用户信息等操作,以及用户此次观看的视频地址以及时间,便于下次打开该界面时继续播放。 | onRestart() or onResume() |
onDestory() | Activity被销毁钱最后一个被调用的方法。这个方法将会发生因为活动将会结束(在活动中调用finish()方法,或者系统临时销毁该实例节约空间。你可以使用isFinishing()方法区别这两种场景)。 | 界面将要销毁,释放一些实例节约空间,如置空List集合等。 |
一个Activity从本质上讲拥有4种状态:
运行:如果当前的activity在前台界面上时(堆栈顶端)。
暂停:如果activity被另一个非全屏活动强占焦点并覆盖时(如弹窗dialog),它将会暂停。一个暂停的活动也是完全活跃的(它的所有的状态和成员信息将会保留,但activity本身将不会再依附于WindowsManager了),在内存极度缺乏的状态会被系统杀死。
停止:如果activity完全被另一个全屏活动遮挡住时,它将会停止。该活动也仍保留全部的状态和成员信息,但将会被隐藏起来不再展示给用户,并且当内存在其他地方被需要时该活动就将会被系统杀死。
重启:如果activity处于暂停或者停止状态,系统将会在内存中终止该活动无论是结束活动或者杀死进程。当它再一次展示给用户时,它必须是完全重启并且恢复到之前的状态。
Activity生命周期 - 简书 (jianshu.com)
参考阅读
垃圾收集器1 - 资本可不会睡觉,同志请抓紧时间! (li-rr.github.io)
首先回顾一下java内存区域:Java内存区域 - 资本可不会睡觉,同志请抓紧时间! (li-rr.github.io)
程序计数器,本地方法栈,虚拟机栈 3个区域随线程而生,随线程而灭,这几个区域的内存分配和回收都具有确定性,不需要考虑如何回收。
在Java堆和方法区中具有不确定性,接口实现的多个类需要的内存可能会不一样,一个方法不同分支所需的内存也不一样,只有在运行的时候才能知道创建了哪些对象,创建了多少对象
引用计数法
在对象中添加一个引用计数器,每当有一个地方引用它时,计数器就加一;任何时刻计数器为零的对象就是不可能再被使用的。
可达性分析法
基本思路:通过称为“GC Roots”的根对象作为起始节点集,从这些节点开始,根据引用关系向下搜索,搜索过程走过的路径被称为“引用链”(Reference Chain),如果某个对象到GC Roots间没有任何引用链相连,则此对象是不可能再次被使用的。
如下对象可认定为”GC Root”对象:
1 | 1. 虚拟机栈(栈帧中的本地变量表)中引用的对象,譬如各个线程被调用的方法堆栈中使用到的参数、局部变量、临时变量等 |
标记清除算法
首先,会先标记所有需要回收的对象,接着将被标记的不可用的对象清除。
优点是算法简单,只需要清理被标记的地址空间。缺点也比较明显,因为标记位置零散,很碎片化,导致被清除完后,可用的地址空间也零零散散。如果连续的可用内存空间少,那么遇到大的内存对象需分配内存时,就很难分配到适宜的连续内存空间。
标记-复制算法
标记-复制算法被简称为复制算法,其是为了解决标记-清除算法面对大量可回收对象时执行效率低的问题。
将内存空间平分为A、B两块,将A中存活的对象移动到B内存块中,再对A块所有对象进行清除。但是这个算法也有明显的缺点,那就是不管A区域或B区域有多少个存活对象,都需要将整块内存分成两个区域,意味着能够真正使用的内存变成了一半,造成内存的利用率不高。
标记整理算法
其标记过程仍然与“标记-清除”算法一样,但后续步骤不是直接对可回收对象进行清理,而是让所有存活对象都向内存空间一端移动,然后直接清理到边界以外的内存。但是,缺点也有,就是多出了将存活内存平移的操作,会降低清除的效率。
将对象进行代的划分,把不同生命周期的对象放在不同的代上使用不同的垃圾回收方式。主要代划分如下:
年轻代(例如:方法的局部变量等)
年老代(例如:缓存对象、单例对象等)
持久代(例如:加载过的类信息)
由上可知:堆大小=新生代+老年代
将朝生夕灭的对象集中放在一起,每次回收时只关注如何保留少量存活而不是去标记那些大量将要被回收的对象,就能以较低代价回收到大量的空间;
如果剩下的都是难以消亡的对象,那把它们集中放在一块,VM便可以用较低的频率来回收这个区域,这兼顾了垃圾收集的时间开销和内存的空间有效利用。
(54条消息) android垃圾回收机制_只管羊毛薅的博客-CSDN博客_android 垃圾回收机制
首先看Activity的生命周期,有:
onCreate()、onStart()、onResume()、onPause()、onStop()、onDestroy()、onRestart()
其中:
onCreate()和onDestroy()是成对关系
onStart()和onStop()是成对关系
onResume()和onPause()是成对关系
然后看Activity的几种状态:
运行状态、暂停状态、停止状态、销毁状态
Activity的几种生存期:
完整生存期、可见生存期、前台生存期
根据生命周期、状态、生存期对Activity做一个解释分析
运行状态:当一个活动位于返回栈的栈顶时该活动就是处于运行状态
暂停状态:当一个活动不处于栈顶位置但仍然可见时,活动处于暂停状态(比如在对话框后面的activity)
停止状态:当一个活动不再处于栈顶位置并且完全不可见时,活动处于停止状态
销毁状态:当一个活动从返回栈中移除后就变成了销毁状态
完整生存期:活动从onCreate()到onDestroy()之间经历的就是完整生存周期
可见生存期:活动在onStart()到onStop()之间经历的就是可见生存期。此时活动可见,即便可能不能与用户交互。
前台生存期:活动在onResume()到onPause之间经历的就是前台生存期。此时活动可见并且能与用户交互。
Fragment的生命周期
Fragment是用来描述一些行为或一部分用户界面在一个Activity中,你可以合并多个fragment在一个单独的activity中建立多个UI面板,同时重用fragment在多个activity中。
它相比Activity可以在一个界面上灵活的替换一部分页面
因为Fragment和Activity是可以通信的,Fragment是一种控制器对象,Activity可以委派它完成一个任务,这些任务通常就是管理用户界面(Activity通过findFragmetById获得Fragment的一个实例,Fragment通过getActivy获得Activity的实例和Context)。
Activity知道如何管理Fragment,因此Fragment的使用需要Activity的支持,使得Fragment的生命周期和Activity的生命周期非常像,很多方法名称都和Activity是一样的。
Fragment的运行状态:
运行状态:当fragment可见,并且它关联的activity处于运行状态,此fragment也处于运行状态。
暂停状态:当一个activity进入暂停状态(比如对话框等未占满屏幕的activity进入栈顶),fragment也进入到暂停状态
停止状态:当一个activity进入停止状态,与之关联的fragment也进入停止状态;或者通过fragment事务的remove和replace方法将fragment移除。如果在事务commit之前调用了addToBackStack()方法,这时的fragment也会停止
销毁状态:Fragment依附Activity存在,当activity被销毁,与之关联的fragment也被销毁。或者通过fragment事务的remove和replace方法将fragment移除。如果在事务commit之前没有调用addToBackStack()方法,这时的fragment也会销毁
fragment和Activity之间的通信:(控件间的相互操作)
fragment
控制fragment
:得到一个Activity
,然后通过这个Activity
的getFragmentManager()
获得该Fragment
的实例。
fragment
控制Activity
:这个很简单。每个Fragment
都有getActivity()
得到一个Activity的实例:
1 | View listView = getActivity().findViewById(R.id.list); |
Activity
控制fragment
:activity也可以获得一个fragment的引用,从而调用fragment中的方法:
1 | xxxFragment xxx=getFragmentManager().findFragmentById(); |
Activity
控制Activity
:这个显然是通过Intent
活动之间的通信完成。别忘了在被打开的活动中创建Intent
和得到Intent
一起进行,写个静态的actionStart()
。
Activity,Service,Receiver 都支持在 Intent 中传递 Bundle 数据,而 Bundle 实现了 Parcelable 接口,可以在不同的进程间进行传输。
Parcelable 实现序列化
Bundle主要用于传递数据;它保存的数据,是以key-value(键值对)的形式存在的。
我们经常使用Bundle在Activity之间传递数据,传递的数据可以是boolean、byte、int、long、float、double、string等基本类型或它们对应的数组,也可以是对象或对象数组。当Bundle传递的是对象或对象数组时,必须实现Serializable 或Parcelable接口。下面分别介绍Activity之间如何传递基本类型、传递对象。
在一个进程中启动了另一个进程的 Activity,Service 和 Receiver ,可以在 Bundle 中附加要传递的数据通过 Intent 发送出去。
Windows 上,一个文件如果被加了排斥锁会导致其他线程无法对其进行访问,包括读和写;而 Android 系统基于 Linux ,使得其并发读取文件没有限制地进行,甚至允许两个线程同时对一个文件进行读写操作,尽管这样可能会出问题。
可以在一个进程中序列化一个对象到文件系统中,在另一个进程中反序列化恢复这个对象(注意:并不是同一个对象,只是内容相同。)。
SharedPreferences 是个特例,系统对它的读 / 写有一定的缓存策略,即内存中会有一份 ShardPreferences 文件的缓存,系统对他的读 / 写就变得不可靠,当面对高并发的读写访问,SharedPreferences 有很多大的几率丢失数据。因此,IPC 不建议采用 SharedPreferences。
暂时放弃
AIDL:Android Interface Definition Language
暂时放弃
用于不同应用间数据共享,和 Messenger 底层实现同样是 Binder 和 AIDL,系统做了封装,使用简单。
系统预置了许多 ContentProvider ,如通讯录、日程表,需要跨进程访问。
使用方法:继承 ContentProvider 类实现 6 个抽象方法,这六个方法均运行在 ContentProvider 进程中,除 onCreate 运行在主线程里,其他五个方法均由外界回调运行在 Binder 线程池中。
ContentProvider 的底层数据,可以是 SQLite 数据库,可以是文件,也可以是内存中的数据。
Socket起源于 Unix,而 Unix 基本哲学之一就是“一切皆文件”,都可以用“打开 open –读写 write/read –关闭 close ”模式来操作。Socket 就是该模式的一个实现,网络的 Socket 数据传输是一种特殊的 I/O,Socket 也是一种文件描述符。Socket 也具有一个类似于打开文件的函数调用: Socket(),该函数返回一个整型的Socket 描述符,随后的连接建立、数据传输等操作都是通过该 Socket 实现的。
常用的 Socket 类型有两种:流式 Socket(SOCK_STREAM)和数据报式 Socket(SOCK_DGRAM)。
Android进程间通信方式 - 简书 (jianshu.com)
为了确定首先执行哪个进程以及最后执行哪个进程以实现最大 CPU 利用率,计算机科学家已经定义了一些算法,它们是:
MVC模式的意思是,软件可以分成三个部分。
1 | 视图(View):用户界面。 |
各部分之间的通信方式如下。
1 | View 传送指令到 Controller |
所有通信都是单向的。
主要处理逻辑为:View触发事件,controller响应并处理逻辑,调用Model,Model处理完成后将数据发送给View,View更新。
MVP 模式将 Controller 改名为 Presenter,同时改变了通信方向。
各部分之间的通信,都是双向的。
View 与 Model 不发生联系,都通过 Presenter 传递。
View 非常薄,不部署任何业务逻辑,称为”被动视图”(Passive View),即没有任何主动性,而 Presenter非常厚,所有逻辑都部署在那里。
MVP模型中,P为Presenter,并以Presenter为核心,负责从model获取数据,并填充到View中。该模型使得Model和View不再有联系,且View被称为“被动视图”,暴露出setter接口。
MVVM 模式将 Presenter 改名为 ViewModel,基本上与 MVP 模式完全一致。
唯一的区别是,它采用双向绑定(data-binding):View的变动,自动反映在 ViewModel,反之亦然。Angular 和 Ember 都采用这种模式。
MVVM模型中,VM为ViewModel,同样是以VM为核心,但是不同于MVP,MVVM采用了数据双向绑定的方案,替代了繁琐复杂的DOM操作。该模型中,View与VM保持同步,View绑定到VM的属性上,如果VM数据发生变化,通过数据绑定的方式,View会自动更新视图;VM同样也暴露出Model中的数据。
Java中默认声明的就是强引用,比如:
1 | Object obj = new Object(); //只要obj还指向Object对象,Object对象就不会被回收 |
只要强引用存在,垃圾回收器将永远不会回收被引用的对象,哪怕内存不足时,JVM也会直接抛出OutOfMemoryError,不会去回收。如果想中断强引用与对象之间的联系,可以显示的将强引用赋值为null,这样一来,JVM就可以适时的回收对象了
软引用是用来描述一些非必需但仍有用的对象。在内存足够的时候,软引用对象不会被回收,只有在内存不足时,系统则会回收软引用对象,如果回收了软引用对象之后仍然没有足够的内存,才会抛出内存溢出异常。这种特性常常被用来实现缓存技术,比如网页缓存,图片缓存等。
用java.lang.ref.SoftReference类来表示软引用。
1 | SoftReference<byte[]> sr = new SoftReference<>(buff); |
弱引用的引用强度比软引用要更弱一些,无论内存是否足够,只要 JVM 开始进行垃圾回收,那些被弱引用关联的对象都会被回收。
用 java.lang.ref.WeakReference 来表示弱引用。
1 | WeakReference<byte[]> sr = new WeakReference<>(buff); |
虚引用是最弱的一种引用关系,如果一个对象仅持有虚引用,那么它就和没有任何引用一样,它随时可能会被回收
定义为:每个数字的十进制表示中(0~9),每个数位各不相同且各个数位之和等于N。
满足条件的数字可能很多,找到其中的最小值即可。
输入描述:
1
2 共一行,一个正整数N,如题意所示,表示组合中数字不同数位之和。
(1 <= N <= 1,000)
输出描述:
1
2 共一行,一个整数,表示该组合中的最小值。
如果组合中没有任何符合条件的数字,那么输出-1即可。
题目分析:
数:123456789 是最小的数位之和,因为题目中限定了每个数位各不相同,
则只需求1-45之间的就行
解法:
1 | def myCompute(num): |
解法二:
1 | def compute(x,num): |
多多君最近在研究字符串之间的变换,可以对字符串进行若干次变换操作:
现在有两个长度相同的字符串X和Y,多多君想知道,如果要将X和Y变成两个一样的字符串,需要的最少的代价之和是多少。
输入描述:
1
2
3
4 共三行,第一行,一个整数N,表示字符串的长度。
(1 <= N <= 2,000)
接下来两行,每行分别是一个字符串,表示字符串X和Y。
(字符串中仅包含小写字母)
输出描述:
1 共一行,一个整数,表示将X和Y变换成一样的字符串需要的最小的总代价。
示例:
输入:
1
2
3 4
abca
abcd输出:
1 3
解法:
1 | def myCompute2(str1,str2): |
多多路上从左到右有N棵树(编号1~N),其中第i个颗树有和谐值Ai。
多多鸡认为,如果一段连续的树,它们的和谐值之和可以被M整除,那么这个区间整体看起来就是和谐的。
现在多多鸡想请你帮忙计算一下,满足和谐条件的区间的数量。
输入描述:
第一行,有2个整数N和M,表示树的数量以及计算和谐值的参数。
( 1 <= N <= 100,000, 1 <= M <= 100 )
第二行,有N个整数Ai, 分别表示第i个颗树的和谐值。
( 0 <= Ai <= 1,000,000,000 )
输出描述:
1 共1行,每行1个整数,表示满足整体是和谐的区间的数量。
解法:
来自牛客评论区
1 | def myCompute3(M,A): |
多多君拼团购买了N个骰子,为了方便后面进行活动,多多君需要将这些骰子进行分类。
两个骰子为同类的定义是:
将其中一个骰子通过若干次上下、左右或前后翻转后,其与另一个骰子对应的6面数字均相等。
现在多多君想知道不同种类的骰子的数量分别有多少。
放弃了
Cookie与Session的区别
进程阻塞的原因
进程有3个状态:就绪态、执行态、阻塞态。三种状态的转换包含有:
就绪->执行,执行->就绪,执行->阻塞,阻塞->就绪
等待I/O、进程sleep、等待解锁等原因都会导致进程暂停。
关于”时间片切换”,当进程已经获得了除cpu外所有的资源,这时的状态就是就绪态,
当分配到了时间片就成了执行态,当时间片用完之前一直未进入阻塞态的话,此后便继续进入就绪态。
页面置换算法中,会产生Belady异常现象的是
所谓Belady现象是指:采用FIFO算法时,如果对—个进程未分配它所要求的全部页面,有时就会出现分配的页面数增多但缺页率反而提高的异常现象。
FIFO的性能较差,因为较早调入的页往往是经常被访问的页,这些页在FIFO算法下会被反复调入和调出。
belady现象的原因是FIFO算法的置换特征与进程访问内存的动态特征是矛盾的,即被置换的页面并不是进程不会访问的。(局部性原理)
TCP的三次握手
第一次握手序列号是x;
第二次握手序列号y,确认号x+1;
第三次握手序列号x+1,确认号y+1
数据库语句
I/O系统硬件结构分为四级:1。设备控制器,2。I/O设备,3。处理机,4。I/O通道,按级别由高到低的顺序是?
处理机(cpu)等级显然是最高的,通道是一个独立于 CPU的专管输入/输出控制的处理机,它控制设备与内存直接进行数据交换。所以通道是第二,通道控制设备控制器,设备控制器控制设备。
网络划分与子网的计算
白盒测试又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。属于白盒测试方法的有哪些?
随机存储设备(RAM)属于内存,硬板、U盘属于外部存储设备。
考察测试用例设计思路,从功能、性能、安全等多方面思考;结合测试用例设计方法回答。
答案要点: 功能测试 1. 正向功能; 2. 参数为空; 3. dealid不存在; 4. dealid为非数字的值; 5. quantity为0或负值; 6. quantity大于库存量; 7. token无效 8. 入参不是JSON 性能测试 1. 压力测试,考察系统在极限压力下的处理能力 2. 狭义性能测试,验证系统能够达到一定的处理能力 3. 并发测试,测试数据库和应用服务器对并发请求的处理 安全性测试 1. 伪造token攻击 2. 订单潮水攻击 3. deal遍历攻击 4. SQL注入攻击 加分项 订单复用:当同一个用户提交的dealid、quantity相同时,返回的orderID总是一样(没有重复创建订单)
已知一个IP地址为10.5.136.5, 子网掩码为255.255.64.0, 他的网络号和主机号分别是?
c语言程序题
1 |
|
哪种协议在数据链路层
ARP:链路层
ICMP:网路层
FTP:应用层
UDP:运输层
删除表A全部数据的方法,一般情况下执行速度最快的是
drop table A 是删除整个表,题目的潜在意思是删除表中的数据而并非删除整个表。
truncate table A是删除表中的数据,删除速度比delete更 快,无法撤回(回退)。
delete from A 删除数据表中的数据,可以回退,可添加where 子句。
速度,一般来说:drop> truncate > delete .
但drop是删除整个表了。
数据库完整性:
实体完整性和参照完整性适用于任何关系型数据库系统,它主要是针对关系的主关键字和外部关键字取值必须有效而做出的约束。
Http状态码,
以下http返回报头有哪几行有错误?
①HTTP/1.1 302 Moved Permanently
Cache-Control: private, no-store, no-cache, must-revalidate
②Expires: Sat, 01 Jan 2000 00:00:00 GMT
Pragma: no-cache
③Content-Type: text/html; charset=utf-8
④Connection: maintain
美团有一个API用于创建团购订单,地址如下
https://open.meituan.com/order/createorder?token=1234567890abcdefghijklmnopqrstuvwxyz
其中,token用于验证用户身份
请求方法:POST
参数类型:application/json
参数列表
1
2
3
4 {
"dealid": 90,
"quantity": 5
}传入deal ID(要购买的团购券的ID)和数量后,返回新生成的订单ID(隐去无关参数)。例如:
1
2
3
4
5 {
"success": 0, // 正常情况为0
"msg": "", // 正常情况为空
"orderid": 2910100100, // 订单id
}
功能测试
性能测试
兼容性测试:
安全性测试:
其他
每年的5月17日,点评都会在全国各大城市举办517吃货节优惠活动,如果你来负责手机端517某一个活动的测试任务,你会想到从哪些方面测试,来保证517活动的质量?
此次活动投放首页上”全城好券”活动中的每日优惠页面
- 用户领取条件:每个商户的券每个用户只能领取一次。
- 券数目限制:每个商户的每天的券有数目限制。
- 领券时间限制:只有上午10点开始可以才可以领券。
功能性测试
兼容性测试
性能相关:
前端性能:CPU,内存占用,低配置Android机体验效果
后端性能:压测对应的后端接口QPS,预测峰值及所对应集群的QPS。
每秒查询率QPS是对一个特定的查询服务器在规定时间内所处理流量多少的衡量标准
用来衡量服务器的机器性能。
网络环境模拟测试:wifi测试、3g/4g/5g,弱网络情况
其他:
## 参考教程
mysql表user已有索引:idx_name_age
(name
,age
)。查询语句select * from user where name='jack' or age = 18
是否经过此索引
private static volatile Long num; 变量num在内存中是否线程安全
jdbc statement
有关java object默认的基本方法
关键字序列为堆的是
1 100,60,70,50,32,65堆有最大堆和最小堆 把序列化为二叉树 判断根结点和左右子树的大小即可
二分查找树的时间复杂度
Java引用数据类型
Java中哪些集合是Collection派生出来的
下列代码输出结果为1的是
1 | int cestcCount=0; |
1 | 1. 排序算法的时间复杂度 |
1
2
3
4
5
6
7 给定英文句子S和字符串x,判断x是否为S中某些单词的前缀,若匹配到则输出第1个匹配单词的位置,否则输出-1。
例如:输入"this is an easy problem."和"eas",输出4
例如:输入"In love folly is always sweet"和"like",输出-1
例如:输入"Whatever is worth doing is worth doing well."和"wor",输出3
Linux下,下列哪些途径不会让程序由用户态切换到内核态
用户态到内核态的三种方式:
- 异常:如果当前进程运行在用户态,如果这个时候发生了异常事件,就会触发切换。例如:缺页异常。
- 系统调用:Linux内核中设置了一组用于实现各种系统功能的子程序,称为系统调用。用户可以通过系统调用命令在自己的应用程序中调用它们。
- 外部访问中断:当外设完成用户的请求时,会向CPU发送中断信号。
n个数值选出最大m个数(3<m<n)的最小算法复杂度是$O(N)$
部分快排 时间复杂度 O(N) 存储复杂度 O(N)
用某种排序方法对关键字序列{135,184,121,147,115,127,168,125,120}进行排序时,序列的变化情况如下:
120,115,121,125,147,127,168,135,184
115,120,121,125,135,127,147,168,184
115,120,121,125,127,135,147,168,184
使用的方法是?
完全二叉树与满二叉树
完全二叉树:
叶节点只能出现在最下层和次下层,并且最下面一层的结点都集中在该层最左边的若干位置的二叉树
满二叉树:
1、一个层数为k 的满二叉树总结点数为:(2^k)-1。因此二叉树的结点树一定是奇数个。
2、第i层上的结点数为:2^(i-1)
3、一个层数为k的满二叉树的叶子结点个数(也就是最后一层):2^(k-1)
16个相同的糖果,分给三个人,每个人至少要得一个。有多少种不同分法?
插空法:16个糖果依次排开,中间有15个空挡 ,依次编号为空挡1-15,从这9个空挡中任意取出2 个作为分割点 ,正好能把糖果分为3份,并且保证每一份中至少有一个糖果。因为分割点并没有顺序,所以可以使用组合公式C(15,2)计算。
现有某图书管理系统,管理员可对所有权限的馆藏图书进行查询,可以根据出版社(电子工业、清华大学)、发行日期(2000-2010,2010-2020)、作者性别(男、女)进行查询,试对该查询功能设计测试用例。(本题中无需考虑无权限的情况)
按照传统设计,设计全部测试用例。(3分)
所在列 | 1 | 2 | 3 |
---|---|---|---|
因素 | 出版社 | 发行日期 | 作者性别 |
实验1 | 电子工业 | 2000-2010 | 男 |
实验2 | 电子工业 | 2000-2010 | 女 |
实验3 | 电子工业 | 2010-2020 | 男 |
实验4 | 电子工业 | 2010-2020 | 女 |
实验5 | 清华大学 | 2000-2010 | 男 |
实验6 | 清华大学 | 2000-2010 | 女 |
实验7 | 清华大学 | 2010-2020 | 男 |
实验8 | 清华大学 | 2010-2020 | 女 |
使用正交试验法设计测试用例(5分)
所在列 | 1 | 2 | 3 |
---|---|---|---|
因素 | 出版社 | 发行日期 | 作者性别 |
实验1 | 电子工业 | 2000-2010 | 男 |
实验2 | 电子工业 | 2010-2020 | 女 |
实验3 | 清华大学 | 2000-2010 | 女 |
实验4 | 清华大学 | 2010-2020 | 男 |
正交实验相当于在别的维度上缩减了实验次数
说明使用正交试验法设计测试用例的好处。
根据正交性从全面试验中挑选出部分有代表性的点进行试验,这些有代表性的特点具备了“均匀分散,整齐可比”的特点。
通过使用正交试验法减少了测试用例,合理地减少测试的工时与费用,提高测试用例的有效性。是一种高效率、快速、经济
的实验设计方法。
某在线支付平台余额提现到银行卡规则:每日累计提现金额不超1万元为快速(2小时)到账; 超过1万元为普通到账,普通到账没有额度上限限制。
要求:
1、假设账户中有5万余额,给出覆盖无效等价类的测试用例。
2、假设账户中有5万余额,给出覆盖有效等价类的测试用例。
3、使用黑盒测试的等价类划分法给出有效等价类和无效等价类。
评分标准: 快速到账和普通到账,以及一天内多次提取是主要答题点,其余根据回答情况酌情给分,总分10分。
1、假设账户中有5万余额,给出覆盖无效等价类的测试用例。
2、假设账户中有5万余额,给出覆盖有效等价类的测试用例。
使用黑盒测试的等价类划分法给出有效等价类和无效等价类。
提现功能分为快速到账和普通到账两个功能:
第一种情况:不考虑一天内多次提取,设计用例如下
第二种情况:考虑一天内多次提取,设计用例如下(6分)
软件系统几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流。
场景法就是通过用例场景描述业务操作流程,从用例开始到结束遍历应用流程上所有基本流(基本事件)和备选流(分支事件)。
下面是对某城市“好莱坞”影院APP购票系统中会员卡使用的基本流和备选流的描述。
会员卡分为储值型会员卡和现金型会员卡两种,会员必须持本卡在本影城内进行刷卡消费,才能享受影城提供的会员购票折扣、积分优惠、积分兑奖、会员专享、会员升级等一系列的会员优惠和服务。
会员种类:
1、现金消费会员卡:6个月内累计观影6次或购影票消费达到200元者,可凭票带有效证件免费100元现金消费会员卡。
2、储值会员卡:分为200元、300元、600元、1000元四种卡。其中:200元为会员卡、300元为银卡会员、600元为金卡会员、1000元为VIP尊贵会员。
问题1:使用场景法设计测试用例,指出场景涉及到的基本流和备选流,基本流用字母A表示,备选流用题干中描述的相应字母表示。
问题2:场景中的每一个场景都需要确定测试用例,一般采用矩阵来确定和管理测试用例。
如下表所示是一种通用格式,其中行代表各个测试用例,列代表测试用例的信息。本例中的测试用例包含测试用例、ID、场景条件、测试用例中涉及的所有数据元素和预期结果等项目。
首先确定执行用例场景所需的数据元素(本例中包括账号、是否黑名单卡、输入购票数量、账面金额、余票量),然后构建矩阵,最后要确定包含执行场景所需的适当条件的测试用例。
在下面的矩阵中,是表示有效数据元素,否表示无效数据元素,n/a表示不适用。例如C01表示“成功购票”基本流。请按上述规定为其它应用场景设计用例矩阵。
问题3:假如每张票20元人民币,用户的账户金额为600元,余票量充足,那么在A4输入购票数量的过程中,
请运用边界值分析方法为A4选取合适的输入数据(即电影票数量,单位:张)。
1、使用场景法设计测试用例
共有5个场景:
场景1:A;场景2:A和B;场景3:A和C,场景4:A和D;场景5:A和E
2、设计用例矩阵
3、用边界值分析方法为A4选取合适的输入数据
1、0张;2、30张;3、31张
先取一个无效输入,再取一个边界值,然后再突破边界值
满减策略是外卖平台推出的一种为了让商家与顾客实惠,平台给予商家补贴,通过这样的营销活动来实现用户高速增长的一种模式。
以某城市外卖平台设计的麻辣香锅或麻辣烫的满减策略为例子,蔬菜成本0.5元,肉类0.8元,在设计满减的时候,可以5元一个档,例:25-13,30-15,35-17……,蔬菜定价3元,荤菜定价5元,这样,每5元一个满减档,用户就会拉高自己的客单价。报价规则如下表所示。
顾客如点的香锅合计32元,实际支付32-15=17元。
现在该商家开发一个软件,输入为实际价格P(1<P<100),输出为满减后价格D。
问题1:请采用等价类划分法为该软件设计测试用例(不考虑P为非整数的情况)
问题2:请采用边界值分析法为该软件设计测试用例(不考虑健壮性测试,既不考虑P不在1到100之间或者是非整数的情况)
问题3:列举除了等价类划分法和边界值分析法以外的三种常见的黑盒测试用例设计方法。
问题1:
设计用例时从这6个等价类中任选一个代表数据即可。
问题2
问题3:
错误推测法,因果图法,判定表驱动法,正交试验法,功能图法等。
HTTP状态码:
301状态码:被请求的资源已永久移动到新位置
401:请求要求身份验证
403:服务器已经理解请求,但拒绝他
404、请求失败,请求所希望得到的资源未被在服务器上发现
503:由于临时的服务器维护或者过载,服务器无法处理请求。
Linux文件权限:
权限项 读 写 执行 读 写 执行 读 写 执行
字符表示 r w x r w x r w x
数字表示 4 2 1 4 2 1 4 2 1
权限分配 owner group other
SQL模型查询使用Like,如要查询表user中name字段中,第2个字母为A的所有数据,sql语句为:
1 | select * from user where name like ’_A%’; |
_
代表占位符,%
代表未知字符
数据结构,强连通图
强连通图:在G中,如果对于每一对vi、vj(vi≠vj),从vi到vj和从vj到vi都存在路径。
n个顶点的有向强连通图:至少n条边(形成一个环);至多n(n-1)条边
n个顶点的无向强连通图:至少n-1条边(形成一条直线);至多n(n-1)/2条边
将50个红球和50个白球放到两个盒子中,从中抽出一个球,那么抽到的是红球的最大概率是:
一个红球放在一个箱子里,其余求全部放到另一个箱子。
这样放的概率为:0.5+0.5*(49/99) 约等于0.75(74/99)。
此时取到红球的概率最大。
测试人员要坚持原则,缺陷未修复完坚决不能上线。
如果是影响严重的缺陷,测试人员需要坚持原则(否组上线后可能引发现网事故或客户投诉);如果是小缺陷或经过专家组评估对现网无影响或风险可控,又基于版本发布的压力(外部压力如客户侧压力等),可适当灵活处理。
自动化测试能比手工测试发现更多的缺陷。
自动化测试只是提高了测试的效率,并不会因为用了自动化就会发现更多的bug。
请尽量多的列举有哪些可能的原因,会导致一个应用的用户帐号无法登录。
请设计稳定且低成本的全自动化方案,获得一台手机的启动时长。
小选线下店最近准备新上架一批长度不等的商品, 用一个数组表示商品的长度,已知货架每一层的长度固定为X。
小选线下店是一个追求生活美学的店铺,为了摆放美观,每一层至多摆放两个商品,而且商品的总长度不能比货架长度长(已知单个商品的长度都不会比货架长)
请问至少需要多少层的货架,才能漂亮的摆放这些商品呢?
分析
先对其进行排序,先考虑一层获取放两个商品的情况,
要想尽可能少用货架,就有一大搭一小,一个从前向后,一个从后向前
如果正好可以放下两个商品,则货架层数加一。然后将这两个货物取消掉。
最后处理单个的情况。
1 | def test3_2(): |
代码:输入一串字符串,返回出现次数大于3的字符
其他代码题:
- [青蛙跳台阶](70. 爬楼梯 - 力扣(LeetCode) (leetcode-cn.com))
- [从乱序序列中找到前K个最大数](347. 前 K 个高频元素 - 力扣(LeetCode) (leetcode-cn.com))
- [输入一个字符串数组,将出现次数大于5的字符串输出](692. 前K个高频单词 - 力扣(LeetCode) (leetcode-cn.com))
- [字符串找出出现次数等于3的字符并拼接为子字符串](692. 前K个高频单词 - 力扣(LeetCode) (leetcode-cn.com))
http,Https的区别
http每次请求都会断开连接吗
在http1.0 中,一个服务器在发送完一个HTTP响应后,会断开TCP连接。但是这样每次请求都会重新建立和断开Tcp连接,代价过大。于是HTTP1.1在Connection: keep-alive 的 Header 进行了持久连接的支持。
怎么设置http请求每次断开
Connection: keep-alive , 开启
Connection: close ,关闭
浏览器可向一个服务端发起多少次http请求,是否有限制
HTTP/1.1
中,单个TCP连接,在同一时间只能处理一个http请求,虽然存在Pipelining技术支持多个请求同时发送,但由于实践中存在很多问题无法解决,所以浏览器默认是关闭,所以可以认为是不支持同时多个请求。
HTTP2
提供了多路传输功能,多个http请求,可以同时在同一个TCP连接中进行传输。
页面资源请求时,浏览器会同时和服务器建立多个TCP连接,在同一个TCP连接上顺序处理多个HTTP请求。所以浏览器的并发性就体现在可以建立多个TCP连接,来支持多个http同时请求。
Chrome浏览器最多允许对同一个域名Host建立6个TCP连接,不同的浏览器有所区别。
为什么有的时候刷新页面不需要重新建立 SSL 连接?
TCP 连接有的时候会被浏览器和服务端维持一段时间。TCP 不需要重新建立,SSL 自然也会用之前的。
浏览器对同一 Host 建立 TCP 连接到数量有没有限制?
有。Chrome 最多允许对同一个 Host 建立六个 TCP 连接,不同的浏览器有一些区别。
若收到的 HTML 如果包含几十个图片标签,这些图片是以什么方式、什么顺序、建立了多少连接、使用什么协议被下载下来的呢?
- 如果图片都是 HTTPS 连接并且在同一个域名下,那么浏览器在 SSL 握手之后会和服务器商量能不能用 HTTP2,如果能的话就使用 Multiplexing 功能在这个连接上进行多路传输。不过也未必会所有挂在这个域名的资源都会使用一个 TCP 连接去获取,但是可以确定的是 Multiplexing 很可能会被用到。
- 如果发现用不了 HTTP2 呢?或者用不了 HTTPS(现实中的 HTTP2 都是在 HTTPS 上实现的,所以也就是只能使用 HTTP/1.1)。那浏览器就会在一个 HOST 上建立多个 TCP 连接,连接数量的最大限制取决于浏览器设置,这些连接会在空闲的时候被浏览器用来发送新的请求,若所有的连接都正在发送请求,那么其他的请求就只能等待。
ssl层公钥、私钥谁拿
- Https是如何加密的
- SSL层如何实现的加密
- 对称加密是有几个随机字符串拼接
- TCP UDP HTTP属于哪一层
接口调不通一直在转圈怎么测试
接口无响应:
接口有响应:但是返回了错误的HTTP状态码,需要根据不同的状态码确定具体原因
json
接口,需要添加一个信息头Content-type:application/json
一条SQL语句:一个表,含车主名和车牌号,输出拥有超过3辆车的车主名
一条SQL语句是怎么执行的
其实我们的 sql 可以分为两种,一种是查询,一种是更新(增加,更新,删除)。
查询语句:我们先分析下查询语句
1 select * from tb_student A where A.age='18' and A.name=' 张三 ';
先检查该语句是否有权限,如果没有权限,直接返回错误信息,如果有权限,在 MySQL8.0 版本以前,会先查询缓存,以这条 sql 语句为 key 在内存中查询是否有结果,如果有直接缓存,如果没有,执行下一步。
通过**分析器进行词法分析,提取 sql 语句的关键元素,比如提取上面这个语句是查询 select,提取需要查询的表名为 tb_student,需要查询所有的列,查询条件是这个表的 id=’1’**。然后判断这个 sql 语句是否有语法错误,比如关键词是否正确等等,如果检查没问题就执行下一步。
接下来就是优化器进行确定执行方案,上面的 sql 语句,可以有两种执行方案:
a. 先查询学生表中姓名为“张三”的学生,然后判断是否年龄是 18。
b. 先找出学生中年龄 18 岁的学生,然后再查询姓名为“张三”的学生。
那么优化器根据自己的优化算法进行选择执行效率最好的一个方案(优化器认为,有时候不一定最好)。那么确认了执行计划后就准备开始执行了。
进行权限校验,如果没有权限就会返回错误信息,如果有权限就会调用数据库引擎接口,返回引擎的执行结果。
以上就是一条查询 sql 的执行流程,那么接下来我们看看一条更新语句如何执行的呢?sql 语句如下:
1 update tb_student A set A.age='19' where A.name=' 张三 ';我们来给张三修改下年龄,在实际数据库肯定不会设置年龄这个字段的,不然要被技术负责人打的。其实这条语句也基本上会沿着上一个查询的流程走,只不过执行更新的时候肯定要记录日志啦,这就会引入日志模块了,MySQL 自带的日志模块是 binlog(归档日志) ,所有的存储引擎都可以使用,我们常用的 InnoDB 引擎还自带了一个日志模块 redo log(重做日志),我们就以 InnoDB 模式下来探讨这个语句的执行流程。流程如下:
- 先查询到张三这一条数据,如果有缓存,也是会用到缓存。
- 然后拿到查询的语句,把 age 改为 19,然后调用引擎 API 接口,写入这一行数据,InnoDB 引擎把数据保存在内存中,同时记录 redo log,此时 redo log 进入 prepare 状态,然后告诉执行器,执行完成了,随时可以提交。
- 执行器收到通知后记录 binlog,然后调用引擎接口,提交 redo log 为提交状态。
- 更新完成。
这里肯定有同学会问,为什么要用两个日志模块,用一个日志模块不行吗?
这是因为最开始 MySQL 并没有 InnoDB 引擎(InnoDB 引擎是其他公司以插件形式插入 MySQL 的),MySQL 自带的引擎是 MyISAM,但是我们知道 redo log 是 InnoDB 引擎特有的,其他存储引擎都没有,这就导致会没有 crash-safe 的能力(crash-safe 的能力即使数据库发生异常重启,之前提交的记录都不会丢失),binlog 日志只能用来归档。
并不是说只用一个日志模块不可以,只是 InnoDB 引擎就是通过 redo log 来支持事务的。那么,又会有同学问,我用两个日志模块,但是不要这么复杂行不行,为什么 redo log 要引入 prepare 预提交状态?这里我们用反证法来说明下为什么要这么做?
- 先写 redo log 直接提交,然后写 binlog,假设写完 redo log 后,机器挂了,binlog 日志没有被写入,那么机器重启后,这台机器会通过 redo log 恢复数据,但是这个时候 bingog 并没有记录该数据,后续进行机器备份的时候,就会丢失这一条数据,同时主从同步也会丢失这一条数据。
- 先写 binlog,然后写 redo log,假设写完了 binlog,机器异常重启了,由于没有 redo log,本机是无法恢复这一条记录的,但是 binlog 又有记录,那么和上面同样的道理,就会产生数据不一致的情况。
如果采用 redo log 两阶段提交的方式就不一样了,写完 binglog 后,然后再提交 redo log 就会防止出现上述的问题,从而保证了数据的一致性。那么问题来了,有没有一个极端的情况呢?
假设 redo log 处于预提交状态,binglog 也已经写完了,这个时候发生了异常重启会怎么样呢? 这个就要依赖于 MySQL 的处理机制了,MySQL 的处理过程如下:
- 判断 redo log 是否完整,如果判断是完整的,就立即提交。
- 如果 redo log 只是预提交但不是 commit 状态,这个时候就会去判断 binlog 是否完整,如果完整就提交 redo log, 不完整就回滚事务。
总结
- 查询语句的执行流程如下:权限校验(如果命中缓存)—>查询缓存—>分析器—>优化器—>权限校验—>执行器—>引擎
- 更新语句执行流程如下:分析器—->权限校验—->执行器—>引擎—redo log(prepare 状态)—>binlog—>redo log(commit状态)
数据库,查询前10行数据:使用limit关键字
索引有哪些
- 主键索引:数据列不允许重复,不能为NULL,一个表只能有一个主键索引
- 组合索引:有多个列值组成的索引
- 唯一索引:数据列不允许重复,可以为NULL,索引列的值必须唯一,如果是组合索引,则列值的组合必须唯一
- 全文索引:对文本的内容进行搜索
- 普通索引:基本的索引类型,可以为NULL
索引的结构
索引的数据结构主要有B+数和哈希表,对应的索引分别为B+树索引和哈希索引。InnoDB引擎的索引类型有B+树索引和哈希索引,默认的索引类型为B+树索引。
在B+树中,所有的记录节点都是按照键值大小的顺序放在叶子节点上,因为B+树具有有序性,并且所有的数据都存放在叶子节点,所以查找的效率非常高,并且支持排序和范围查找。
B+树的索引又可以分为主索引和辅助索引。其中主索引为聚簇索引,辅助索引为非聚簇索引。
聚簇索引是以主键作为B+ 树索引的键值所构成的B+树索引,聚簇索引的叶子节点存储着完整的数据记录;非聚簇索引是以非主键的列作为B+树索引的键值所构成的B+树索引,非聚簇索引的叶子节点存储着主键值。
所以使用非聚簇索引进行查询时,会先找到主键值,然后到根据聚簇索引找到主键对应的数据域。
哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列通过哈希算法进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的,将哈希码的值作为哈希表的key值,将指向数据行的指针作为哈希表的value值。这样查找一个数据的时间复杂度就是o(1),一般多用于精确查找。
为什么不用B树
B树与B+树的区别:
- B树中的内部节点和叶子节点存放键和值,而B+树的内部节点只有键没有值,叶子节点存放所有的键和值
- B+树的叶子节点通过链表连接在一起,方便顺序检索。
不用B树的原因如下:
- B树适用于随机检索,而B+树适用于随机检索和顺序检索
- B+树的空间利用率更高,因为B树每个节点要存储键和值,而B+树的内部节点只存储键,这样B+树的一个节点就可以存储更多的索引,从而使树的高度变低,减少了I/O次数,使得数据检索速度更快。
- B+树的叶子节点都是连接在一起的,所以范围查找,顺序查找更加方便
- B+树的性能更加稳定,因为在B+树中,每次查询都是从根节点到叶子节点,而在B树中,要查询的值可能不在叶子节点,在内部节点就已经找到。
如何分析一条SQL语句执行的性能
使用[Explain](Mysql调优 - 资本可不会睡觉,同志请抓紧时间! (li-rr.github.io))关键字
什么情况下索引会失效
- 条件中有
or
,例如select * from table_name where a = 1 or b = 3
- 在索引上进行计算会导致索引失效,例如
select * from table_name where a + 1 = 2
- 索引字段上使用 is null/is not null判断时会导致索引失效,例如
select * from table_name where a is null
- 索引上使用!、=、<>进行判断时会导致索引失效,例如
select * from table_name where a != 1
- 在索引中使用函数会导致索引失效,例如
select * from table_name where abs(a) = 1
索引的最左匹配原则:
最左匹配原则:从最左边为起点开始连续匹配,遇到范围查询(<、>、between、like)会停止匹配。
例如建立索引(a,b,c),大家可以猜测以下几种情况是否用到了索引。
第一种
1
2 select * from table_name where a = 1 and b = 2 and c = 3
select * from table_name where b = 2 and a = 1 and c = 3上面两次查询过程中所有值都用到了索引,where后面字段调换不会影响查询结果,因为MySQL中的优化器会自动优化查询顺序。
第二种
1
2
3 select * from table_name where a = 1
select * from table_name where a = 1 and b = 2
select * from table_name where a = 1 and b = 2 and c = 3答案是三个查询语句都用到了索引,因为三个语句都是从最左开始匹配的。
第三种
1
2 select * from table_name where b = 1
select * from table_name where b = 1 and c = 2答案是这两个查询语句都没有用到索引,因为不是从最左边开始匹配的
第四种
1 select * from table_name where a = 1 and c = 2这个查询语句只有a列用到了索引,c列没有用到索引,因为中间跳过了b列,不是从最左开始连续匹配的。
第五种
1 select * from table_name where a = 1 and b < 3 and c < 1这个查询中只有a列和b列使用到了索引,而c列没有使用索引,因为根据最左匹配查询原则,遇到范围查询会停止。
第六种
1
2
3 select * from table_name where a like 'ab%';
select * from table_name where a like '%ab'
select * from table_name where a like '%ab%'sql题主要考察两表连接和group by
linux
查找一个文件里所有的”error”
grep -e “error” test.txt
linux
查找当下这个目录里所有文件的Error:grep -e "error" text.txt
查看服务器端口
sudo netstat -apn | grep "80"
在一个文件中查找某个字符在哪一行
grep -n "fuck" test.txt
服务器能有多少个端口
nmap ip
可以探测服务器开放了多少个端口如何查看本地到服务器间通不通
- ping ip ——-测试看本机 和 对应的ip的机器是否是通,有返回的字节数可以证明ip是通的
- telnet ip port —- 可以测试查看端口是否开启
linux查看日志
linux查看文件数量
统计当前目录下文件的个数(不包括子目录)
1 ls -l | grep "^-" | wc -l统计当前目录下文件的个数(包括子目录)
1 ls -lR | grep "^-" | wc -l查看某目录下文件夹(目录)的个数(包括子目录)
1 ls -lR | grep "^d" | wc -l
并发,多线程,多进程的区别
验证码怎么测试
为什么找测开
你做测开的优缺点
自我介绍
项目介绍,难点,怎么解决的
python异常了解吗
try except
python打开文件方法
open, with open as f:
python多线程,以及实现过程
使用threading模块
tcp三次握手、四次挥手
http请求方法,post、get区别(好像也记混了,脑子当时不知道在干啥)
在请求的url中携带数据;在请求体中携带数据
404状态码
资源没有找到,请求错误
selenium元素定位方位,xpath优缺点
selenium在使用元素定位方法时遇到错误,怎么解决(回答的是没有解决🤣)
linux查看内存、cpu命令
二面
自我介绍
实习内容
怎么写测试点测试用例
我们写用例的时候一般是先写测试点,然后再写测试用例,也可以这么理解,测试点就是精简版的测试用例。
编写用例四个基本方法:等价类、边界值、正交法、场景法。
编写测试用例的策略:先点后面,先局部再整体,最忌讳的是点和面混在一起,局部和整体不明。
一个任务做测试的时间是多久
如何提升测试速度
多线程
反问
初试
数据库:
终试
对测试行业的了解?
做测试应该要有一定的协调能力,因为测试人员经常要与开发接触处理一些问题,如果处理不好的话会引起一些冲突,这样的话工作上就会不好做。还有测试人员要有一定的耐心,有的时候做测试很枯燥乏味。除了耐心,测试人员不能放过每一个可能的错误。
以前实习的测试流程?
测试需要哪些技能?怎么去学习这些技能
比起其他人你的优势在哪?
初试
数据库ACID是什么,举例
Atom,原子性:直白点说就是一个事务中的所有操作(CRUD)就像是一个原子操作一样不可分割开来,要么全部成功,要么全部失败,不允许部分成功部分失败。
例,
这两个动作要么都成功,要么都失败,不存在只往篮子里放苹果而没拿梨,也不存在只从篮子里拿梨而没有放苹果。
原子性的侧重点在于多个动作必须同时成功或者同时失败。
Consistency,一致性:一致性和原子性的区别在于两者的侧重点不同,原子性关注的是状态,要么全部成功,要么全部失败,不存在部分成功的状态。而一致性关注的是数据的可见性,一个事务的中间状态的数据对外部不可见,只有最初状态和最终状态的数据对外可见。
事务的隔离级别就是在事务的四要素和性能上面做平衡,有时候为了提高性能,会适度的破坏一致性原则。
说回到主题一致性的理解上,我对一致性的理解是这样的,一致性关注的点是数据的操作结果是否与用户业务预期一致,这里有两点需要注意。
Isolation,隔离性:并发事务之间不会互相影响,就像串行执行一样,也就是说并发事务之间都是互相隔离的,你不影响我,我也不影响你。
隔离性侧重点是并发事务之间的影响,说到并发事务就要提到数据库的隔离级别,有的时候会通过调整数据库的隔离级别来适度的破坏一致性和隔离性,从而提高数据库处理性能。
ps. 画外音,隔离性是我们需要重点关注的,因为不同的隔离级别,可能对应的加锁过程不一样,而正是因为引入了各种各样的隔离级别,才让锁问题变得格外复杂。解决和分析死锁问题,重点就是要搞清楚数据库的隔离级别。那么隔离级别是个什么东西呢?我们会在后面出单独的文章来重点说明。
Durability,持久性:持久性就非常好理解了,事务提交后即持久化到磁盘不会丢失。
持久性侧重的是数据不丢失,这个跟网上讨论最多的 (“丢失更新”、“提交覆盖”、“Read-Modify-Write问题”)很容易混淆,看起来效果都是没有存入正确的数据,看起来好像数据丢失了一样。
实际上两者区别很大的,前者是说数据存到物理磁盘不会丢失,而后者则说的是并发事务中的相互影响导致最终的数据结果不同。
参考链接:一分钟弄清楚事务四要素:ACID | 凝雨 - Yun | 快乐编程每一天 - Happy Coding Every Day (ningyu1.github.io)
算法题求1-100内的素数
进程通信方式(4种)
测试的方法,框架,工具了解哪些
复试
项目介绍,细节要搞清楚
手撕
扫码支付设计测试用例
测试用例:
用户角度:
功能性测试:用户能否成功生成用于支付的二维码或二维码,二维码出现后屏幕能否变成增亮的模式,用户能否成功选取不同的付款方式,比如“花呗”、“账户余额”、“余额宝”、“银行账户”等。
扫码完成后,用户能否收到支付成功的界面,并且界面能正确显示用户支付的金额,包括付款信息、是否使用优惠、折扣等。
界面测试:打开支付宝后,能否正确显示界面,二维码的界面是否正确,支付的每个步骤界面是否正确。不会出现前端界面错误,或者打开不了界面。
易用性测试:在整个用户支付的过程中,操作步骤是否简易方便。
兼容性:测试扫码支付功能,在不同手机品牌,不同操作系统下是否兼容。
安全测试:二维码如果超过安全时间后能否自动更新为新的二维码。测试整个支付流程的安全机制能否成功实现。
压力测试:持续的扫码,测试扫码支付功能在强压的状态下,工作状态如何。
网络测试:测试在不同网络环境下,不同网络信号强度的情况下,整个支付流程是否出现卡顿,卡顿的点容易出现在哪里。
商家角度:
功能性测试:扫码枪能否成功扫到用户手机中的二维码,扫码成功后能否收到钱,并且成功生成收款的界面。支付宝后台、商家后台、用户手机能否成功传输支付结果信息。
易用性测试:在不同光线,屏幕不同亮度的情况下,能否成功完成扫码收款的功能。
hr面
一面
二面
介绍简历中的实习经历,你有什么收获
你为什么想要从事测试开发工程师
从技术角度来说,你觉得测试开发工程师需要掌握哪些技能?在这些技能中,你觉得你的掌握程度怎么样
你对自己的测试开发的职业规划是什么样的
首先快速熟悉业务,熟悉环境,了解自动化技术在部门业务的应用,然后主动研究,往技术上面考虑
是否了解自动化测试
对于一名测试工程师而言,连续的开发周期需要重复执行相同的测试用例组成的测试套件。如果每一次都手动执行此过程,可能会非常重复且耗时,很容易让人产生疲倦感。但是通过利用测试自动化工具,可以更轻松地编写测试套件,按需重手动执行,减轻人为干预并提高测试。
DDL和DML的区别是什么
如何测试一个台灯
如何测试一个柜子
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n
级的台阶总共有多少种跳法。
用两个栈实现一个队列。队列的声明如下,请实现它的两个函数 appendTail 和 deleteHead ,分别完成在队列尾部插入整数和在队列头部删除整数的功能。(若队列中没有元素,deleteHead 操作返回 -1 )