算法
1、排序都有哪几种方法?
2、最小生成树
1.Kruskal算法
此算法可以称为“加边法”,初始最小生成树边数为0,每迭代一次就选择一条满足条件的最小代价边,加入到最小生成树的边集合里。
1. 把图中的所有边按代价从小到大排序;
2. 把图中的n个顶点看成独立的n棵树组成的森林;
3. 按权值从小到大选择边,所选的边连接的两个顶点ui,viui,vi,应属于两颗不同的树,则成为最小生成树的一条边,并将这两颗树合并作为一颗树。
4. 重复(3),直到所有顶点都在一颗树内或者有n-1条边为止。
2.Prim算法
此算法可以称为“加点法”,每次迭代选择代价最小的边对应的点,加入到最小生成树中。算法从某一个顶点s开始,逐渐长大覆盖整个连通网的所有顶点。
- 图的所有顶点集合为VV;初始令集合u={s},v=V−uu={s},v=V−u;
- 在两个集合u,vu,v能够组成的边中,选择一条代价最小的边(u0,v0)(u0,v0),加入到最小生成树中,并把v0v0并入到集合u中。
- 重复上述步骤,直到最小生成树有n-1条边或者n个顶点为止。
由于不断向集合u中加点,所以最小代价边必须同步更新;需要建立一个辅助数组closedge,用来维护集合v中每个顶点与集合u中最小代价边信息,:
struct{ char vertexData //表示u中顶点信息 UINT lowestcost //最小代价}closedge[vexCounts]
3、常见Hash算法,哈希的原理和代价
MD4 MD5 SHA-1
4、全排列、贪心算法、KMP算法、hash算法
全排列:递归遍历数组,然后生成N个子数组,再递归拆解。如:45的全排列为 45 54 ;345的全排列为 345 354 435 453 543 534。
KMP算法的思想是对主串s和子串(模式)t进行模式匹配,主串中的字符只匹配一次。主串只遍历一次,保证每次子串遍历(移动位置根据当前所在子串位置前半部分和后半部分等于主串的所在位置的前后字符串)
5、一致性Hash算法
设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似
数据库
1、数据库事务和隔离级别
2、为什么需要锁,锁定分类,锁粒度
为什么需要锁?
数据库是多用户共享资源的,在并发环境下会破坏数据库的一致性,所以需要锁来控制它们。
锁定机制分类:
排他锁/X锁:
仅允许一个事务封锁此页;其他任何事务必须等到排他锁被释放才能对该页进行访问;排他锁一直到事务结束才能被释放。
共享锁/S锁:
能够阻塞其他事务进行的锁,例如事务A+S锁,B事务就不能排他锁了,只能对A进行S锁,依次类推按有规划的执行。
更新锁/U锁:
更新锁在修改操作的初始化阶段用来锁定可能要被修改的资源,这样可以避免使用共享锁造成的死锁现象。
在使用共享锁的时候,数据的修改分为两部分:
1.获取共享锁,去读数据。
2.变为排他锁,执行修改操作。
如果多个事务同时对一个事务申请了共享锁,在数据修改的时候,这些事务都要将共享锁升级为排它锁。这时,这些事务都不会释放共享锁而是一直等待对方释放,这样就造成了死锁。如果一个数据在修改前直接申请更新锁,在数据修改的时候再升级为排它锁,就可以避免死锁。
锁的粒度:
排他锁和共享锁都是加载某一个数据对象上的,这就是数据的粒度。
按封锁的数据粒度分类如下:
行级锁定(row-level)
粒度最小、发生锁冲突概率最低、并发度最高、开销大、加锁慢、会出现死锁。
表级锁定(table-level)
粒度大、发生锁冲突概率最高、并发度最低、开销小、加锁快、不会出现死锁。
页级锁定(page-level)
粒度界于表锁和行锁之间、开销和加锁时间界于表锁和行锁之间、并发度一般、会出现死锁。
3、乐观锁,悲观锁的概念及实现方式
5、分页如何实现(Oracle,MySql)
oracle: rownum ; mysql : limit
6、Mysql引擎
InnoDB存储引擎
InnoDB是事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键,InnoDB是默认的MySQL引擎。InnoDB主要特性有:
1、InnoDB给MySQL提供了具有提交、回滚和崩溃恢复能力的事物安全(ACID兼容)存储引擎。InnoDB锁定在行级并且也在SELECT语句中提供一个类似Oracle的非锁定读。这些功能增加了多用户部署和性能。在SQL查询中,可以自由地将InnoDB类型的表和其他MySQL的表类型混合起来,甚至在同一个查询中也可以混合
2、InnoDB是为处理巨大数据量的最大性能设计。它的CPU效率可能是任何其他基于磁盘的关系型数据库引擎锁不能匹敌的
3、InnoDB存储引擎完全与MySQL服务器整合,InnoDB存储引擎为在主内存中缓存数据和索引而维持它自己的缓冲池。InnoDB将它的表和索引在一个逻辑表空间中,表空间可以包含数个文件(或原始磁盘文件)。这与MyISAM表不同,比如在MyISAM表中每个表被存放在分离的文件中。InnoDB表可以是任何尺寸,即使在文件尺寸被限制为2GB的操作系统上
4、InnoDB支持外键完整性约束,存储表中的数据时,每张表的存储都按主键顺序存放,如果没有显示在表定义时指定主键,InnoDB会为每一行生成一个6字节的ROWID,并以此作为主键
5、InnoDB被用在众多需要高性能的大型数据库站点上
InnoDB不创建目录,使用InnoDB时,MySQL将在MySQL数据目录下创建一个名为ibdata1的10MB大小的自动扩展数据文件,以及两个名为ib_logfile0和ib_logfile1的5MB大小的日志文件
MyISAM存储引擎
MyISAM基于ISAM存储引擎,并对其进行扩展。它是在Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM拥有较高的插入、查询速度,但不支持事物。MyISAM主要特性有:
1、大文件(达到63位文件长度)在支持大文件的文件系统和操作系统上被支持
2、当把删除和更新及插入操作混合使用的时候,动态尺寸的行产生更少碎片。这要通过合并相邻被删除的块,以及若下一个块被删除,就扩展到下一块自动完成
3、每个MyISAM表最大索引数是64,这可以通过重新编译来改变。每个索引最大的列数是16
4、最大的键长度是1000字节,这也可以通过编译来改变,对于键长度超过250字节的情况,一个超过1024字节的键将被用上
5、BLOB和TEXT列可以被索引
6、NULL被允许在索引的列中,这个值占每个键的0~1个字节
7、所有数字键值以高字节优先被存储以允许一个更高的索引压缩
8、每个MyISAM类型的表都有一个AUTO_INCREMENT的内部列,当INSERT和UPDATE操作的时候该列被更新,同时AUTO_INCREMENT列将被刷新。所以说,MyISAM类型表的AUTO_INCREMENT列更新比InnoDB类型的AUTO_INCREMENT更快
9、可以把数据文件和索引文件放在不同目
10、每个字符列可以有不同的字符集
11、有VARCHAR的表可以固定或动态记录长度
12、VARCHAR和CHAR列可以多达64KB
MEMORY存储引擎
7、MYSQL语句优化
8、从一张大表读取数据,如何解决性能问题
- 1、用索引提高效率du:
- 2、选择有效率的表名顺序,及数据结构及字段;
- 3、使用DECODE函数可以避免重复扫描相同记录或重复连接相同的表;
- 4、删除重复记;
- 5、通过内部函数提高SQL效率;......
9、内连接,左连接,右连接作用及区别
10、索引以及索引的实现(B+树介绍、和B树、R树区别
1)B树
B树中每个节点包含了键值和键值对于的数据对象存放地址指针,所以成功搜索一个对象可以不用到达树的叶节点。
成功搜索包括节点内搜索和沿某一路径的搜索,成功搜索时间取决于关键码所在的层次以及节点内关键码的数量。
在B树中查找给定关键字的方法是:首先把根结点取来,在根结点所包含的关键字K1,…,kj查找给定的关键字(可用顺序查找或二分查找法),若找到等于给定值的关键字,则查找成功;否则,一定可以确定要查的关键字在某个Ki或Ki+1之间,于是取Pi所指的下一层索引节点块继续查找,直到找到,或指针Pi为空时查找失败。
2)B+树
B+树非叶节点中存放的关键码并不指示数据对象的地址指针,非叶子节点只是索引部分。所有的叶节点在同一层上,包含了全部关键码和相应数据对象的存放地址指针,且叶节点按关键码从小到大顺序链接。如果实际数据对象按加入的顺序存储而不是按关键码次数存储的话,叶节点的索引必须是稠密索引,若实际数据存储按关键码次序存放的话,叶节点索引时稀疏索引。
B+树有2个头指针,一个是树的根节点,一个是最小关键码的叶节点。
所以 B+树有两种搜索方法:
一种是按叶节点自己拉起的链表顺序搜索。
一种是从根节点开始搜索,和B树类似,不过如果非叶节点的关键码等于给定值,搜索并不停止,而是继续沿右指针,一直查到叶节点上的关键码。所以无论搜索是否成功,都将走完树的所有层。
B+ 树中,数据对象的插入和删除仅在叶节点上进行。
这两种处理索引的数据结构的不同之处:
a,B树中同一键值不会出现多次,并且它有可能出现在叶结点,也有可能出现在非叶结点中。而B+树的键一定会出现在叶结点中,并且有可能在非叶结点中也有可能重复出现,以维持B+树的平衡。
b,因为B树键位置不定,且在整个树结构中只出现一次,虽然可以节省存储空间,但使得在插入、删除操作复杂度明显增加。B+树相比来说是一种较好的折中。
c,B树的查询效率与键在树中的位置有关,最大时间复杂度与B+树相同(在叶结点的时候),最小时间复杂度为1(在根结点的时候)。而B+树的时候复杂度对某建成的树是固定的。
多线程
1、进程和线程的区别
进程里面可以有多个线程。都是cpu消费时间段。进程颗粒度更大
2、并行和并发的区别和联系
- 解释一:并行是指两个或者多个事件在同一时刻发生;而并发是指两个或多个事件在同一时间间隔发生。
- 解释二:并行是在不同实体上的多个事件,并发是在同一实体上的多个事件。
- 解释三:并行是在多台处理器上同时处理多个任务。如 hadoop 分布式集群,并发是在一台处理器上“同时”处理多个任务。
所以并发编程的目标是充分的利用处理器的每一个核,以达到最高的处理性能。
并行(parallel):指在同一时刻,有多条指令在多个处理器上同时执行。所以无论从微观还是从宏观来看,二者都是一起执行的。
并发(concurrency):指在同一时刻只能有一条指令执行,但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个进程快速交替的执行。
3、同步与异步
一直做直到得出结果;异步:你先做,回头告知结果就行
5、什么叫守护线程
6、如何停止一个线程?
- 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
- 使用stop方法强行终止,但是不推荐这个方法,因为stop和suspend及resume一样都是过期作废的方法。
- 使用interrupt方法中断线程。
7、什么是线程安全?synchronized和 lock的区别synchronized
8、启动一个线程是用run还是start?
启动一个线程是调用start()方法,使线程所代表的虚拟处理机处于可运行状态,这意味着它可以由JVM调度并执行。这并不意味着线程就会立即运行。run()方法可以产生必须退出的标志来停止一个线程。
9、wait和sleep的区别 - 1、sleep是线程中的方法,但是wait是Object中的方法。
- 2、sleep方法不会释放lock,但是wait会释放,而且会加入到等待队列中。
- 3、sleep方法不依赖于同步器synchronized,但是wait需要依赖synchronized关键字。
- 4、sleep不需要被唤醒(休眠之后推出阻塞),但是wait需要(不指定时间需要被别人中断)。
10、notify和notifyAll的区别
唤醒线程,notifyAll唤醒全部的去争夺锁,没争夺到的继续等待。
11、线程池的作用 - 第一:降低资源消耗。通过重复利用已创建的线程降低线程创建和销毁造成的消耗。
- 第二:提高响应速度。当任务到达时,任务可以不需要等到线程创建就能立即执行。
- 第三:提高线程的可管理性。
12、Java中线程池相关的类
Executor
newCachedThreadPool 带缓冲功能的
newFixedThreadPool 可重用的
newScheduledThreadPool 指定了线程数
newWorkStealingPool(int parallelism) 创建持有足够的线程池来支持给定的并行级别,使用多个队列来减少竞争。
WEB安全
1、什么是SQL注入 ,如何避免。
SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。
2、什么是XSS攻击,如何避免
XSS 攻击,即跨站脚本攻击(Cross Site Scripting),它是 web 程序中常见的漏洞。
web 页面中可由用户输入的地方,如果对输入的数据转义、过滤处理
后台输出页面的时候,也需要对输出内容进行转义、过滤处理(因为攻击者可能通过其他方式把恶意脚本写入数据库)
前端对 html 标签属性、css 属性赋值的地方进行校验
3、什么是CSRF攻击,如何避免
CSRF(Cross-site request forgery)也被称为 one-click attack或者 session riding,中文全称是叫跨站请求伪造。
1.验证 HTTP Referer 字段
HTTP头中的Referer字段记录了该 HTTP 请求的来源地址。在通常情况下,访问一个安全受限页面的请求来自于同一个网站,而如果黑客要对其实施 CSRF
攻击,他一般只能在他自己的网站构造请求。因此,可以通过验证Referer值来防御CSRF 攻击。
2.使用验证码
关键操作页面加上验证码,后台收到请求后通过判断验证码可以防御CSRF。但这种方法对用户不太友好。
3.在请求地址中添加token并验证
CSRF 攻击之所以能够成功,是因为黑客可以完全伪造用户的请求,该请求中所有的用户验证信息都是存在于cookie中,因此黑客可以在不知道这些验证信息的情况下直接利用用户自己的cookie 来通过安全验证。要抵御 CSRF,关键在于在请求中放入黑客所不能伪造的信息,并且该信息不存在于 cookie 之中。可以在 HTTP 请求中以参数的形式加入一个随机产生的 token,并在服务器端建立一个拦截器来验证这个 token,如果请求中没有token或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。这种方法要比检查 Referer 要安全一些,token 可以在用户登陆后产生并放于session之中,然后在每次请求时把token 从 session 中拿出,与请求中的 token 进行比对,但这种方法的难点在于如何把 token 以参数的形式加入请求。
对于 GET 请求,token 将附在请求地址之后,这样 URL 就变成 http://url?csrftoken=tokenvalue。
而对于 POST 请求来说,要在 form 的最后加上 ,这样就把token以参数的形式加入请求了。
4.在HTTP 头中自定义属性并验证
动态代理
1、Java的动态代理的概念
2、Java的动态代理的实现
动态代理的步骤:
-
- 首先获得一个被代理对象的引用,
-
- 获得该引用的接口
-
- 生成一个类,这个类实现了我们给的代理对象所实现的接口
-
- 上述类编译生成了.class字节码供JVM使用
-
- 调用上述生成的class
编码问题
1、常用的字符编码
2、如何解决中文乱码问题