目录
1.抽象类可以用final修饰吗?
2.string常用方法
3.hashmap实现原理
4.hashMap 和hashTable区别
6.运行时异常
7.常见的http码值
8.mysql中的char和varchar的区别
9.mysql获取当前日期
10.oracle同义词
11.union和union all区别
12.mysql提高效率/Sql优化
13.常见的SQL注入的类型
14.xss csrf了解吗
15.Spring的AOP和IOC
16.aop切面编程有用到项目中吗,应用场景
17.Spring mvc和struts有什么区别
18.Spring mvc请求流程
19.Springmvc的控制器是单例的吗,会有什么问题?
20.创建线程方式
21.线程中的run 和start区别
22.死锁造成的原因
23.redis支持的数据类型
24.为什么redis是单线程的,使用还比较快
25.redis持久化方案及优缺点
26.Springboot和Springmvc区别
27.简单介绍一下Springboot
28.SpringbootApplication由哪些组成
29.负载均衡
30.sql语句的执行计划
31.mysql和Oracle的分页有什么区别
32.redis中map怎么增加删除数据
33.系统数据量大吗?并发量大吗?
不能,定义抽象类就是让其他类继承的,如果定义为 final 该类就不能被继承,这样彼此就会产生矛盾,编辑器也会报错,所以 final 不能修饰抽象类。
(1)int length(); 语法:字符串名.length(); 返回值为 int 类型。得到一个字符串的字符个数(中、英、空格、转义字符皆为字符,计入长度)。
(2)char charAt(值); 语法 :字符串名.charAt(值); 返回值为 char 类型。从字符串中取出指定位置的字符。
(3)char toCharArray(); 语法 :字符串名.toCharArray(); 返回值为 char 数组类型。将字符串变成一个字符数组。
(4)int indexOf("字符"); 语法 :字符串名.indexOf("字符") / 字符串名.indexOf("字符",值);查找一个指定的字符串是否存在,返回的是字符串的位置,如果不存在,则返回-1 。
in lastIndexOf("字符"); 得到指定内容最后一次出现的下标。
(5)toUpperCase(); toLowerCase(); 语法 :字符串名.toUpperCase(); 字符串大小写的转换。
(6)String[] split("字符"); 语法 :字符串名.split("字符"); 根据给定的正则表达式的匹配来拆分此字符串。形成一个新的String数组。
(7)trim(); 去掉字符串左右空格。 replace(char oldChar,char newChar); 新字符替换旧字符,也可以达到去空格的效果一种。
(8)String substring(int beginIndex,int endIndex); 截取字符串。
(9)boolean equalsIgnoreCase(String); 忽略大小写的比较两个字符串的值是否一模一样,返回一个布尔值。
(10)boolean equals(Object anObject); 语法 :字符串变量名.wquals(字符串变量名); 返回值为布尔类型。所以这里用 if 演示。比较两个字符串是否相等,返回布尔值
(11)boolean contains(String); 判断一个字符串里面是否包含指定的内容,返回一个布尔值
(12)boolean startsWith(String); 测试此字符串是否以指定的前缀开始。返回一个布尔值。boolean endsWith() 测试此字符串是否以指定的后缀结束。返回一个布尔值。
HashMap是基于哈希表的Map接口的非同步实现(此实现提供所有可选的映射操作),并允许使用null值和null键。HashMap储存的是键值对,HashMap很快。此类不保证映射的顺序,特别是它不保证该顺序恒久不变。HashMap实际上是一个“链表散列”的数据结构,即数组和链表的结合体,后来1.8就是数组加链表+红黑树。
采用entry数组存储键值对,每个键值对就是一个entry实体,put()操作。
有一个addEntry()方法,先进行容量的判断,如果当前容量达到了阈值并且需要存储到数组中就会进行扩容,重新计算hash的值,和数组的存储位置,扩容后的链表顺序与扩容前的链表顺序相反1.8之前就是把新插入的元素放在链表的头部,1.8之后就是放在链表的尾部
1.8之后当阈值达到一定值时(8)就会转换成红黑树。 ,特点不会有两个红色的节点相连;
线程安全 | 是否允许null | 效率 | 是否同步 | 部分api不同 | 继承类 | hash算法 | 容量 | |
hashMap | 不安全 | 允许null值null键 | 效率较高 | 方法不是synchronized的,要提供外同步 | 有containsvalue和containsKey方法 | 继承于AbstractMap | 添加元素时,是使用自定义的哈希算法 | 初始容量16,填充因子默认0.75,扩容时:capacity*2 |
hashTable | 安全 | 不允许null值null键 | 效率较低 | 方法是synchronized的 | 有contains方法 | 继承于Dictionary | 没有自定义哈希算法,而直接采用的key的hashCode() | 初始容量11,填充因子默认0.75,扩容时:capacity*2+1 |
两者都是键值对方式存储,HashMap只支持Iterator(迭代器)遍历。
而Hashtable支持Iterator(迭代器)和Enumeration(枚举器)两种方式遍历。
HashMap是“从前向后”的遍历数组;再对数组具体某一项对应的链表,从表头开始进行遍历。
Hashtabl是“从后往前”的遍历数组;再对数组具体某一项对应的链表,从表头开始进行遍历。
1、cookie数据存放在客户的浏览器上,session数据放在服务器上。
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。
3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。
4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。(Session对象没有对存储的数据量的限制,其中可以保存更为复杂的数据类型)
5、设置cookie时间可以使cookie过期。但是使用session-destory(),我们将会销毁会话。
6、所以个人建议:将登陆信息等重要信息存放为SESSION,其他信息如果需要保留,可以放在COOKIE中。
注意:
session很容易失效,用户体验很差;
虽然cookie不安全,但是可以加密 ;
cookie也分为永久和暂时存在的;
浏览器 有禁止cookie功能 ,但一般用户都不会设置;
一定要设置失效时间,要不然浏览器关闭就消失了;
NullPointerException - 空指针引用异常
ClassCastException - 类型强制转换异常。
IllegalArgumentException - 传递非法参数异常。
ArithmeticException - 算术运算异常
ClassNotFoundException - 找不到指定的类
IndexOutOfBoundsException - 下标越界异常
NumberFormatException - 数字格式异常
IOException - 输入输出异常
SQLException - SQL语句执行异常
NegativeArraySizeException - 创建一个大小为负数的数组错误异常
SecurityException - 安全异常
UnsupportedOperationException - 不支持的操作异常
ArrayStoreException - 向数组中存放与声明类型不兼容对象异常
IllegalAccessException - 无访问权限异常
状态码分类表:
码值 | 类别 | 原因 |
1XX | Informational(信息性状态码) | 接受的请求正在处理 |
2XX | Success(成功状态码) | 请求正常处理完毕 |
3XX | Redirection(重定向) | 需要进行附加操作以完成请求 |
4XX | Client error(客户端错误) | 客户端请求出错,服务器无法处理请求 |
5XX | Server Error(服务器错误) | 服务器处理请求出错 |
1XX 信息提示
1xx状态码是 HTTP/1.1 版本新定义的,用来表示请求被正常接受,会进行进一步处理。这些状态码相对较新,并且 HTTP/1.0 版本无法识别,所以原则上不应该向HTTP/1.0版本的客户端发送任何1xx状态码。
100——Continue:请求者应当继续提出请求。服务器返回此代码表示已收到请求的第一部分,正在等待其余部分。
2XX 成功
200——OK:表示从客户端发送给服务器的请求被正常处理并返回;
204——No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206——Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3XX 重定向
301——Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302——Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;使用cas 重定向
301与302的区别:301是永久移动,302是临时移动(之后可能还会更改URL)
303——See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:303明确表示客户端应当采用GET方式获取资源
304——Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307——Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4XX 客户端错误
400——Bad Request:表示请求报文中存在语法错误;
401——Unauthorized:未经许可,需要通过HTTP认证;没有访问权限
403——Forbidden:服务器拒绝该次访问(访问权限出现问题),授权失败
404——Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
405:请求的方法不支持,服务器要求post,客户端使用get请求
406:客户请求要求返回json格式,服务器值返回text/plan格式。
5XX 服务器错误
500——Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503——Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
char是一种固定长度的类型,效率较高;varchar则是一种可变长度的类型,效率较低;它们的区别是:
char(M)类型的数据列里,每个值都占用M个字节,如果某个长度小于M,MySQL就会在它的右边用空格字符补足.(在检索操作中那些填补出来的空格字符将被去掉)在varchar(M)类型的数据列里,每个值只占用刚好够用的字节再加上一个用来记录其长度的字节(即总长度为L+1字节).
char | varchar | |
类型 | 定长,不够的长度用空格填充 | 不定长,保留实际字符 |
最大长度 | 255字节 | 65535字节 |
空间 | 可能浪费 | 更加节省 |
效率 | 更高 | 较低 |
尾部空格 | 插入时省略 | 插入时不会省略,查找时可省略 |
like查找 | 语句中like后的' '不会省略 | 语句中like后的' '不会省略,字段结尾的空格也不省略 |
例如:
char (16)长度固定, 如'www.baidu.com' 需要存储空间 13个字符。
varchar(16)可变长, 如'www.baidu.com' 需要存储空间 16个字符。
从上面可以看得出来char 长度是固定的,不管你存储的数据是多少他都会都固定的长度。而varchar则是可变长度,他会在总长度上加3个字符。
1.1 获得当前日期+时间(date + time)函数:now();执行开始时值就得到了
1.2 获得当前日期+时间(date + time)函数:sysdate();函数执行时动态得值
由下图对比可以看出,now()和sysdate()区别,前者执行开始时间就得到了,后者是动态获取时间
2. 获得当前日期(date)函数:curdate()
3. 获得当前时间(time)函数:curtime()
4. 获得当前 UTC 日期时间函数:utc_date(), utc_time(), utc_timestamp();UTC 时间在业务涉及多个国家和地区的时候,非常有用。因为我国位于东八时区,所以本地时间 = UTC 时间 + 8 小时。
同义词是现有对象的一个别名,是为了简化SQL语句,亦或者是隐藏对象的名称和所有者,提供对象的公共访问等等。
1、同义词的类型 :
分为两大类 :私有同义词 synonym 只能在其模式内访问,不能与模式内对象同名。
公有同义词 public synonym 可被所有数据库用户访问。
2、同义词的建立
first step : 同义词的创建需要有创建同义词的权利。
system 赋予你: grant create (public) synonym to 用户名;
second:create [ or replace ] synonym 同义词名 for 同义词指代内容;
create [ or replace ] public synonym 同义词名 for 同义词指代内容;
3、删除同义词
删除同义词也要有删除同义词的权限 drop (public)synonym;
删除私有同义词:drop synonym 同义词名;
删除公有同义词:drop public synonym 同义词名;
4、举个栗子
create or replace public synonym syn_emp for scott.emp;
create users test1 identified by test1 ;
grant connect session to test1;
select * from syn_emp; -- syn_emp 是预先创建好的公有同义词。
报错,原因如下
在上述例子中,test1用户不具有访问scott用户的emp表的权限,故其也同样不具有以scott用户的emp表作为基表的公有同义词。 如果我们赋予test1访问该表的权限,那么我们也就具有了访问指代该表同义词的权限。
常见的公有同义词 著名的 select * from tab;
————————————————
原文链接:https://blog.csdn.net/bibibrave/article/details/80887330
union: 对两个结果集进行并集操作, 不包括重复行,相当于distinct, 同时进行默认规则的排序;会对获取的结果进行排序操作。
union all: 对两个结果集进行并集操作, 包括重复行, 即所有的结果全部显示, 不管是不是重复;不会对获取的结果进行排序操作。
总结:
union all只是合并查询结果,并不会进行去重和排序操作;union会进行去重和排序操作;在没有去重的前提下,使用union all的执行效率要比union高。
1、对查询进行优化,避免全表扫描,首先应考虑在where及order by涉及的列上建立索引。
2、避免在where子句对字段进行null值判断,否则会导致引擎放弃使用索引而进行全表扫描。
3、应尽量避免在where子句中使用!=或者<>操作符,否则引擎放弃索引使用全表扫描。
4、应尽量避免在where子句中使用or来连接条件,否则将导致引擎放弃使用索引而进行全表扫描(可以考虑使用union连接来替代)。
5、in 和 not in 也要慎用,否则会导致全表扫描(对于连续的数值能用between就不要用in)。
6、使用了`%xxx%`或者`%xxx`导致全表扫描,(若要提高效率考虑使用覆盖索引)。
7、应尽量避免在where子句中对字段进行表达式或者函数操作,这将导致引擎放弃使用索引而进行全表扫描。
8、在使用索引字段作为条件时,如果该索引是符合索引,那么必须使用到该索引中第一个字段作为条件时才能保证系统使用到该索引,否则该索引不被使用,并且应尽可能的让字段顺序与索引顺序相一致(虽然MySQL底层会优化)。
9、很多时候使用 exists 代替 in 是一个很不错的选择。
10、不使用ORDER BY RAND()。
11、如果排序字段没有用到索引,就尽量少排序。
12、当只需要一条数据的时候,使用limit 1。
13、索引并不是越多越好,索引固然可以提高相应的select查询效率,但是同时也降低了insert和update的效率,因为insert和update有可能会重建索引,一个表的索引数最好不要超过6个。
14、不要使用select *,可以写明需要查询的字段
XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。此漏洞也是网站存在相当多的漏洞,仅次于SQL注入,攻击者可以使用XSS来绕过访问控制,如同源策略。利用XSS可以窃取账号,网页挂马,发动拒绝服务攻击,发送垃圾邮件等等。
XSS攻击的危害包括
1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击
CSRF(Cross-site request forgery),也被称为:one click attack/session riding,中文名称:跨站请求伪造,缩写为:CSRF/XSRF。
一般来说,攻击者通过伪造用户的浏览器的请求,向访问一个用户自己曾经认证访问过的网站发送出去,使目标网站接收并误以为是用户的真实操作而去执行命令。常用于盗取账号、转账、发送虚假消息等。攻击者利用网站对请求的验证漏洞而实现这样的攻击行为,网站能够确认请求来源于用户的浏览器,却不能验证请求是否源于用户的真实意愿下的操作行为。
你也可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账......造成的问题包括:个人隐私泄露以及财产安全。
CSRF攻击攻击原理及过程如下:
1. 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
2.在用户信息通过验证后,网站A产生Cookie信息并返回给浏览器,此时用户登录网站A成功,可以正常发送请求到网站A;
3. 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
4. 网站B接收到用户请求后,返回一些攻击性代码,并发出一个请求要求访问第三方站点A;
5. 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
Spring 的优点?
1.降低了组件之间的耦合性 ,实现了软件各层之间的解耦
2.可以使用容易提供的众多服务,如事务管理,消息服务等
3.容器提供单例模式支持
4.容器提供了AOP技术,利用它很容易实现如权限拦截,运行期监控等功能
5.容器提供了众多的辅助类,能加快应用的开发
6.spring对于主流的应用框架提供了集成支持,如hibernate,JPA,Struts等
7.spring属于低侵入式设计,代码的污染极低
8.独立于各种应用服务器
9.spring的DI机制降低了业务对象替换的复杂性
10.Spring的高度开放性,并不强制应用完全依赖于Spring,开发者可以自由选择spring的部分或全部
什么是DI(IOC)机制?
依赖注入(Dependecy Injection)和控制反转(Inversion of Control)是同一个概念,具体的讲:当某个角色需要另外一个角色协助的时候,在传统的程序设计过程中,通常由调用者来创建被调用者的实例。但在spring中创建被调用者的工作不再由调用者来完成,因此称为控制反转。创建被调用者的工作由spring来完成,然后注入调用者,因此也称为依赖注入。
spring常用的注入方式主要有三种:构造方法注入,set注入,基于注解的注入
设置注入的优点:直观,自然
构造注入的优点:可以在构造器中决定依赖关系的顺序。
什么是AOP?
面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。
在不影响原来功能代码的基础上,使用动态代理加入自己需要的一些功能(比如权限的验证,事务的控制,日志的记录等等),移除之后,并不影响原来的功能。
面向切面编程是通过动态代理实现的,是对面向对象思想的补充。
主要是管理系统层的业务,比如日志,权限,事物等。AOP是将封装好的对象剖开,找出其中对多个对象产生影响的公共行为,并将其封装为一个可重用的模块,这个模块被命名为切面(aspect),切面将那些与业务逻辑无关,却被业务模块共同调用的逻辑提取并封装起来,减少了系统中的重复代码,降低了模块间的耦合度,同时提高了系统的可维护性。
面向切面编程在Spring中主要表现为两个方面 :
1.面向切面编程提供声明式事务管理
2.Spring支持用户自定义的切面
AOP框架具有的两个特征:
1.各个步骤之间的良好隔离性
2.源代码无关性
主要是管理系统层的业务,比如事务管理、性能监视、安全检查、缓存 、日志,权限等。
1.拦截机制不同
Struts2是类级别的拦截,每次请求就会创建一个Action,和Spring整合时Struts2的ActionBean注入作用域是原型模式prototype,然后通过setter,getter吧request数据注入到属性。Struts2中,一个Action对应一个request,response上下文,在接收参数时,可以通过属性接收,这说明属性参数是让多个方法共享的。Struts2中Action的一个方法可以对应一个url,而其类属性却被所有方法共享,这也就无法用注解或其他方式标识其所属方法了,只能设计为多例。
SpringMVC是方法级别的拦截,一个方法对应一个Request上下文,所以方法直接基本上是独立的,独享request,response数据。而每个方法同时又何一个url对应,参数的传递是直接注入到方法中的,是方法所独有的。处理结果通过ModeMap返回给框架。在Spring整合时,SpringMVC的Controller Bean默认单例模式Singleton,所以默认对所有的请求,只会创建一个Controller,有应为没有共享的属性,所以是线程安全的,如果要改变默认的作用域,需要添加@Scope注解修改。
Struts2有自己的拦截Interceptor机制,SpringMVC这是用的是独立的Aop方式,这样导致Struts2的配置文件量还是比SpringMVC大。
2.底层框架不同
Struts2采用Filter(StrutsPrepareAndExecuteFilter)实现,SpringMVC(DispatcherServlet)则采用Servlet实现。Filter在容器启动之后即初始化;服务停止以后坠毁,晚于Servlet。Servlet在是在调用时初始化,先于Filter调用,服务停止后销毁。
3.性能方面
Struts2是类级别的拦截,每次请求对应实例一个新的Action,需要加载所有的属性值注入,SpringMVC实现了零配置,由于SpringMVC基于方法的拦截,有加载一次单例模式bean注入。所以,SpringMVC开发效率和性能高于Struts2。
4.配置方面
spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高。
5.设计思想
struts更加符合oop的编程思想, spring就比较谨慎,在servlet上扩展。
6.集成方面
SpringMVC集成了Ajax,使用非常方便,只需一个注解@ResponseBody就可以实现,然后直接返回响应文本即可,而Struts2拦截器集成了Ajax,在Action中处理时一般必须安装插件或者自己写代码集成进去,使用起来也相对不方便。
第一步:用户发起请求到前端控制器(DispatcherServlet)
第二步:前端控制器请求处理器映射器(HandlerMappering)去查找处理器(Handle):通过xml配置或者注解进行查找
第三步:找到以后处理器映射器(HandlerMappering)像前端控制器返回执行链(HandlerExecutionChain)
第四步:前端控制器(DispatcherServlet)调用处理器适配器(HandlerAdapter)去执行处理器(Handler)
第五步:处理器适配器去执行Handler
第六步:Handler执行完给处理器适配器返回ModelAndView
第七步:处理器适配器向前端控制器返回ModelAndView
第八步:前端控制器请求视图解析器(ViewResolver)去进行视图解析
第九步:视图解析器像前端控制器返回View
第十步:前端控制器对视图进行渲染
第十一步:前端控制器向用户响应结果
控制器默认是单例的,单例模式下遇见多线程会出现线程安全问题。
在Controller类中不能写类变量(属性),因为单例模式下这个变量是共享的,如果多个请求进来其中某个请求修改了这个类变量的值,在其他请求中也能读到这个修改后的内容,所以在类中没有成员变量的前提下它是线程安全的,非要使用变量且保证线程安全的话,可以使用ThreadLocal变量;也可以通过注解@Scope(“prototype”)或者在配置文件中声明scope="prototype",将其设置为多例模式。
单例bean与原型bean的区别:
如果一个bean被声明为单例的时候,在处理多次请求的时候在Spring容器里只实例化出一个bean,后续的请求都公用这个对象,这个对象会保存在一个map里面。
当有请求来的时候会先从缓存(map)里查看有没有,有的话直接使用这个对象,没有的话才实例化一个新的对象,所以这是个单例的。
但是对于原型(prototype)bean来说当每次请求来的时候直接实例化新的bean,没有缓存以及从缓存查的过程。
源码分析:
生成bean时先判断单例还是原型,如果是单例的则先尝试从缓存里获取,没有再新创建。
单例bean的优点:
减少了新生成实例的消耗。新生成实例消耗包括两方面。第一,Spring会通过反射或者cglib来生成bean实例,这都是耗性能的操作,其次给对象分配内存也会涉及复杂算法。
减少jvm垃圾回收。由于不会给每个请求都生成新bean实例,所以回收的对象也就少了。
可以快速获取到bean。因为单例的获取bean操作除了第一次生成之外其余的都是从缓存里获取的,所以很快。
单例bean的缺点:
单例bean的一个很大的劣势就是他不能做到线程安全!!!由于所有请求都共享一个bean实例,所以这个bean要是有状态的话,可能在并发场景下出现问题,而原型的bean则不会有这个问题(但也有例外,比如他被单例bean依赖)。
第一种 继承Thread类,重写run方法(该方法的方法体就是线程需要执行的任务),调用start()开启线程(需要实例Thread子类,而后用实例后的子类开启线程)。
第二种 实现Runnable接口,重写run方法,调用start()方法开启线程(需要创建Thread对象,然后用其去实例参数是这个实现类,实际就是用实例后的Thread对象开启线程)。
第三种 实现Callable接口,重写call方法,有返回值(可以通过FutureTask类获取线程返回值),调用start()开启线程(需要创建Tread对象,然后去实例化参数是获取到的返回值对象,最后用Thread对象开启线程)。
第四种 通过线程池创建,用Executors类创建线程池(包括缓存线程池newCachedThreadPool(),固定大小线程池newFixedThreadPool(),只创建单个线程newSingleThreadExecutor())或者用new ThreadPoolExecutor()创建自定义的线程池,用创建好的线程池调用execute()处理Runnable类及其run()方法,最后调用线程池的shutdown()方法。
可用性排序:
线程池 > Callable> Runnable > Thread
start()方法是用来启动线程的,使线程处于就绪状态,而run()方法只是Thread类的一个普通方法,在主线程里执行。
当调用start()方法,将会创建一个新线程去执行run()方法中的代码。但直接调用run()方法,会直接在当前线程中执行其run()中的代码,不会创建新线程。
当一个线程启动后,不能重复调用start(),否则会报IllegalStateException异常,但可以重复调用run()方法。
run方法的访问修饰符必须是public,返回类型为void。
死锁:指多个线程因竞争资源而造成的一种僵局(互相等待),若无外力作用,这些进程都将无法向前推进。
死锁产生原因:
1)因为系统的资源不足,不能满足进程的资源请求,会导致多个线程同时争夺一个资源
2)进程运行推进的顺序不合适
3)资源分配不当,有的进程资源分配太少,会因为争夺资源而陷入死锁
死锁产生的必要条件:
互斥条件:一个资源一次只能被一个线程使用,当该线程使用该资源的时候,其他线程就不能使用,具有独占性;
请求与保持条件:一个线程要请求新的资源,但同时对已获得的资源不释放,要等待其他线程释放资源;
循环等待条件:多个线程都要申请资源,但是都对已获得的资源不释放,都要等待其他线程释放资源,多个线程陷入循环等待资源;
不剥夺条件:线程已获得的资源,在未使用完之前,不能被强行剥夺。
解决方法:
1.加锁顺序(线程按照一定的顺序加锁)
2.加锁时限(线程尝试获取锁的时候加上一定的时限,超过时限则放弃对该锁的请求,并释放自己占有的锁)
string(字符串),hash(哈希),list(队列),set(集合)及zset(sorted set:有序集合)。
1、完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。数据存在内存中,类似于HashMap
,HashMap
的优势就是查找和操作的时间复杂度都是O(1);
2、数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;
3、采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;
4、使用多路I/O复用模型,非阻塞IO;
5、使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;
RDB优点:
(1)RDB文件紧凑,全量备份,非常适合用于进行备份和灾难恢复。
(2)生成RDB文件的时候,redis主进程会fork()一个子进程来处理
所有保存工作,主进程不需要进行任何磁盘IO操作。
(3)RDB 在恢复大数据集时的速度比 AOF 的恢复速度要快。
RDB缺点:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大.
(2) 快照持久化期间修改的数据不会被保存,可能丢失数据。数据完整性比较差。
AOF优点:
(1)AOF可以更好的保护数据不丢失,一般AOF会每隔1秒,
通过一个后台线程执行一次fsync操作,最多丢失1秒钟的数据。
(2)AOF日志文件没有任何磁盘寻址的开销,写入性能非常高,文件不容易破损。
(3)AOF日志文件即使过大的时候,出现后台重写操作,也不会影响客户端的读写。
AOF缺点:
(1)对于同一份数据来说,AOF日志文件通常比RDB数据快照文件更大.
(2)恢复数据时时间要比快照模式慢很多。
springboot是一个自动配置化的工具,springMVC是一个web框架。
springboot实现了自动配置,降低项目搭建的复杂度。它主要是为了解决使用Spring框架需要大量的配置,并不是为了替代Spring的解决方案,它是和Spring框架结合用于提升开发者体验的工具,同时继承了大量第三方库框架,简化项目搭建过程。如果承载的是web项目,使用的是SpringMVC作为MVC框架,其工作流程和SpringMVC是相同的,因为这部分就是SpringMVC做的。
springMVC提供了一种轻度耦合的方式来开发web项目。它是Spring的一个模块,一个web框架。通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL路由,Session,模板引擎,静态web资源等。
Spring Boot是由Pivotal团队提供的全新框架,其设计目的是用来简化Spring应用的创建、运行、调试、部署等。使用Spring Boot可以做到专注于Spring应用的开发,而无需过多关注XML的配置。Spring Boot使用“习惯优于配置”的理念,简单来说,它提供了一堆依赖打包,并已经按照使用习惯解决了依赖问题。使用Spring Boot可以不用或者只需要很少的Spring配置就可以让企业项目快速运行起来。
1. @SpringBootConfiguration 通过@Configuration 与@Bean结合,注册到Spring ioc 容器。
2. @ComponentScan 通过范围扫描的方式,扫描特定注解类,将其注册到Spring ioc 容器。
3. @EnableAutoConfiguration 通过spring.factories的配置,来实现bean的注册到Spring ioc 容器。
Dubbo 中使用的5种负载均衡:
1.RandomLoadBalance(随机算法) 是一种比较容易实现的负载均衡策略,也是Dubbo 默认使用的负载均衡策略。就是通过加权的随机,负载均衡分发请求。
2.LeastActiveLoadBalance(最少活跃数算法) 最小活跃度轮询,也就是优先选择活跃度最小的服务进行调用,活跃度简单来说就是服务调用的次数,通过一个 ConcurrentHashMap存储调用服务的次数,获取最小的调用,如果存在多个最小的则通过上面随机的方式调用。
3.ConsistentHashLoadBalance(一致性Hash算法) 一致性Hash 就是通过请求参数来具体定位服务的方式,Dubbo 通过一致性Hash 算法得到具体的服务地址,为了防止资源倾斜,又加入了虚拟节点。
4.RoundRobinLoadBalance(轮询算法) 加权重的轮询算法,通过权重来模拟实现轮询。每个服务会维护一个静态的权重,以及不断变化的动态权重。每次服务会选择动态权重最大的服务,然后将该服务的动态权重剪去总权重,再下次计算动态权重就是通过【原权重】+【动态权重】得到,也就是权重高的经过选择之后,权重会变低,而没有被选择的服务权重会慢慢变高,起到加权以及轮询的作用。
5.ShortestResponseLoadBalance(最短响应时间算法) 也就是调用负载均衡响应时间最多的服务,如果有多个就通过加权的随机来选择,和 LeastActiveLoadBalance 类似,都是去一个 ConcurrentHashMap 中取值,取得历次响应时间的平均,然后比较。
explain 命令主要用于查看 SQL 语句的执行计划,该命令可以模拟优化器执行 SQL 查询语句,可以帮助我们编写和优化 SQL。
使用方式: explain + 待执行的sql
explain 会返回一个待执行 SQL 的执行计划列表,列表包含了 12 个字段,字段共同描述了 SQL 在执行计划中将会采取何种方式执行。以下列表详细描述了执行计划表的字段含义:
字段名称 |
描述 |
---|---|
id |
执行 select 语句查询的序列号,决定表的读取顺序 |
select_type |
查询的类型,也就是数据读取操作的操作类型 |
table |
查询的表名 |
partitions |
表分区 |
type |
访问类型 |
possible_keys |
可使用的索引。 查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用到。 如果这个字段为 null 但是字段 key 不为 null,这种情况就是在查找时没有可以使用的二级索引树, 但是二级索引中包含了需要查询的字段,于是就不再查找聚簇索引(聚簇索引比较大), 转而扫描这个二级索引树(二级索引树比较小), 并且此时一般访问类型 type 为 index,及扫描整棵索引树。 |
key |
实际扫描使用的索引。 如果为 null,则没有使用索引; 查询中若使用了覆盖索引,则该索引仅出现在key列表中; |
key_len |
索引中使用的字节数。 可通过该列计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短越好; key_len 显示的值为索引字段的最大可能长度,并非实际使用长度, 即 key_len 是根据表定义计算而得,不是通过表内检索出的; |
ref |
显示索引的哪一列被使用了。 如果可能的话,是一个常数,哪些列或常量别用于查找索引列上的值; |
rows |
根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数; |
filtered |
搜索条件过滤后剩余数据的百分比。 |
Extra |
包含不适合在其它列中显示但十分重要的额外信息 |
ID列:
执行步骤的编号,编号越大越线执行,编号相同从上到下执行。
SELECT_TYPE列:
SIMPLE:表示不需要union操作或不包含子查询的select语句,有连接查询时外层的查询寻为simple,且只有一个。
PRIMARY:表示需要union操作或包含子查询的select语句,位于最外层的查询select_type为primary,且只有一个。
UNION:表示连接两个select查询,第一个查询时dervied派生表,之外的表都是union。
UNION RESULT:表示包含union的结果集,再union和union all语句中,因为不参与查询,id列的值为NULL。
DEPENDENT UNION:与union类似,表示这个查询要受到外部查询的影响。
SUBQUERY:除了from子句中包含的子查询外,其他地方出现的子查询都可能时subquery。
DEPENDENT_SUBQUERY:与dependent union类似,表示这个查询要受到外部查询的影响。
DERVIED:表示from子句中出现的子查询,也叫做派生表,其他数据库中内联视图或嵌套查询。
MATERIALIZATION:物化通过将子查询的结果作为一个临时表来提高查询速度,一般来说常驻内存,下次查询会再次引用临时表。
TABLE列:
表示显示查询表名,如果有别名,则显示别名,如果不涉及数据库的操作则显示null,如果时尖括号括起来的,如
TYPE列:
按照性能从好到差排列 system>const>eq_ref>ref>fulltext>ref_or_null>unique_subquery>index_subquery>range>index_merge>index>all
SYSTEM表示表中只有一行数据或空表,且只用于myisam引擎的表,如果时innoDB引擎的表则该列通常展示ALL或index。
CONST表示使用唯一索引或主键且返回的记录只有一条记录的等值条件查询,也叫做唯一索引扫描。
EQ_REF表示出现在要连接多个表的查询计划中,驱动表循环获取数据,这行数据是第二个表的主键或唯一索引作为查询条件只返回一条数据,且必须是not null,唯一索引和主键是多列时只有所有的列都用作比较时才会出现eq_ref
REF表时不像eq_ref要求连接顺序,也没有主键和唯一索引的要求,只要使用等值条件检索时就可能出现,常见与辅助索引的等值查找或多列主键/唯一索引中除第一个列之外的等值查找也会出现,返回的记录不确定。
FULLTEXT表示全文检索索引,全文检索索引优先级很高,如果全文检索索引和普通索引同时存在则优先使用全文检索索引。
REF_OR_NULL表示与ref方法类似,增加了null值的比较。
UNIQUE_SUBQUERY表示用于where子句中in形式的查询,子查询返回的记录不重复的唯一值。
INDEX_SUBQUERY表示in形式的子查询使用到了辅助索引或in常数列表,子查询可能返回重复值可以使用索引将结果去重。
RANGE表示范围索引扫描,常见于>,<,between,in,like,is null等运算的查询中。
INDEX_MERGE表示查询使用了两个以上的索引,左后取交集或者并集,常见 and 和or使用了不同的索引.
INDEX表示索引全表扫描
ALL表示全表扫描数据文件,再在server层过滤返回符合要求的记录。
KEY列:
查询真正使用到的索引,type为index_merge时这里会出现两个以上的索引,其他的select_type这里只出现一个。
KEY_LEN列:
索引关键字的长度。
REF列:
如果使用常数等值查询,这里会显示const,如果时连接,表驱动表的执行计划会显示驱动表的关联字段,如果条件使用了表达式或函数或条件列发生了隐式转换,则显示func
EXTRA列:
no table used:不带from子句的查询或者from dual。
NULL:查询的列未被索引覆盖,并且where的筛选条件是索引的前导列,意味着用到了索引但部分字敦未被索引覆盖,必须使用回表来实现,不是纯粹的引用了索引也不是完全没有用到索引。
using index:不需要回表查询。直接使用索引就可以了。
using where:查询的列未被索引覆盖,where筛选条件非索引的前导列。
using where using index:查询的列被索引覆盖,并且where筛选条件是索引列之一,但不是索引的前导列,意味着的无法直接通过索引来获得符合条件的数据。
using index condition:查询的列不完全被索引覆盖,where条件中是一个前导列的范围。
using temporary:表示使用了临时表存储中间结果,可以是内存临时表或磁盘临时表。
using filesort:mysql会使用一个外部的索引对结果进行排序,有较大的开销,需要考虑用索引来优化。
using intersect:表示使用and的各个条件时该信息表示从处理结果获取交集。
using union:表示使用or连接各个使用索引的条件时,该信息表示从处理结果获取并集。
FILTERED列:
存储引擎返回数据在server层过滤后剩下多小满足查询条件的比例,值是百分比。
1、oracle使用rownum进行分页操作,rownum只能比较小于不能比较大于,因为该方法都是先查询后排序的;
2、mysql使用limit进行分页操作,limit中的参数值不能在语句当中写计算表达式,需要提前计算。
一、Mysql使用limit分页
select * from stu limit m, n; //m = (startPage-1)*pageSize,n = pageSize
PS:
(1)第一个参数值m表示起始行,第二个参数表示取多少行(页面大小)
(2)m= (2-1)*10+1,n=10 ,表示 limit 11,10从11行开始,取10行,即第2页数据。
(3)m、n参数值不能在语句当中写计算表达式,写到语句之前必须计算好值。
二、Oracle使用rownum分页
select * from (
select rownum rn,a.* from table_name a where rownum <= x
//结束行,x = startPage*pageSize
)
where rn >= y; //起始行,y = (startPage-1)*pageSize+1
PS:
(1)>= y,<= x表示从第y行(起始行)~x行(结束行) 。
(2)rownum只能比较小于,不能比较大于,因为rownum是先查询后排序的,例如你的条件为rownum>1,当查询到第一条数据,rownum为1,则不符合条件。第2、3...类似,一直不符合条件,所以一直没有返回结果。所以查询的时候需要设置别名,然后查询完成之后再通过调用别名进行大于的判断。
增加:
hset myhash field1 "s" 将myhash中为field1的字段值设为s 。
hsetnx myhash field1 "s" 若字段field1不存在,将设置field1的value为s,若field1存在,则无效。
hmset myhash field1 "hello" field2 "world" 一次性设置多个字段。
删除:
hdel myhash field1 删除 myhash 键中字段名为 field1 的字段和值
del myhash 删除键
修改:
hincrby myhash field 1 给field的值加1
查询:
hget myhash field1 获取键值为 myhash,字段为 field1 的值
hlen myhash 获取myhash键的字段数量
hexists myhash field1 判断 myhash 键中是否存在字段名为 field1 的字段
hmget myhash field1 field2 field3 一次性获取多个字段
hgetall myhash 返回 myhash 键的所有字段及其值
hkeys myhash 获取myhash 键中所有字段的名字
hvals myhash 获取 myhash 键中所有字段的值
主要就是如何解决高并发:
1.系统拆分,将一个系统拆分多个子系统,用dubbo将每个系统连成一个数据库,多数据库可以抗高并发。
2.缓存:数据库和缓存各存一份数据,读数据从缓存里读,redis缓存走内存,天然抗高并发。
3.MQ 消息队列:大量写请求灌入MQ,排队等待,后面系统消费慢慢玩,使用MQ异步写,提升并发性,MQ单机抗几万并发也是ok的。
4.分库分表:一个数据库拆分多个库,多个库抗击高并发,一个表拆分多个表,提高SQL跑的性能。
5.读写分离:主从架构,主库负责写,从库负责读,读流量大时,还可以增加更多的从库。
6.SolrCloud(solr 云)是Solr提供的分布式搜索方案,可以解决海量数据的 分布式全文检索,
因为搭建了集群,因此具备高可用的特性,同时对数据进行主从备份,避免了单点故障问题。可以做到数据的快速恢复。并且可以动态的添加新的节点,再对数据进行平衡,可以做到负载均衡:
7.使用nginx生成静态页面