总结一下最近这几天的面试中所面试到的题,为日后再复习准备,以后再继续总结
J2EE
synchronized和java.util.concurrent.Locks.Lock的异同
- synchronized是类关键字,而Lock是个接口
- synchronized会自动释放锁,而Lock不自己释放锁
- 通过Lock能提高多个线程读操作的效率
- 通过Lock可以知道线程有没有拿到锁,而synchronized不能
- synchronized可以锁类,方法,代码块,而Lock是块范围内的。
- Lock相比synchronized的优势是,可中断、公平锁多个锁。
java的数据结构
java有8中数据类型,分别为数组(Array)、栈(Stack)、队列(Queue)、堆(Heap)、链表(Linked List)、图(Graph)、树(Tree)、散列表(Hash)
子类继承父类之后执行顺序
父类代码
public class Dome {
static {
System.out.println("父类静态块");
}
public Dome() {
System.out.println("父类无参构造器");
}
{
System.out.println("父类非静态方法");
}
public static void test() {
System.out.println("父类静态代码");
}
}
子类代码
public class Dome2 extends Dome{
static {
System.out.println("子类静态块");
}
public Dome2() {
System.out.println("子类无参构造器");
}
{
System.out.println("子类非静态方法");
}
public static void test() {
System.out.println("子类静态代码");
}
}
执行结果
父类静态块
子类静态块
父类非静态方法
父类无参构造器
子类非静态方法
子类无参构造器
J2SE
servlet
servlet中的方法以及用途
Httpservlet中的方法有 init(),service(),destory()等个方法
- init()方法:
在servlet的生命周期中,仅执行一次init()方法。它是在服务器装入servlet的时候执行的。 - service()方法:
service()方法是servlet的核心,每当一个客户请求一个HttpServlet对象,该对象的service()方法就要被调用,而且传递给这个方法一个“请求”(ServletRequest)对象和一个“响应”(ServletResponse)对象作为参数。如果HTTP请求方法为GET,则缺省情况下就调用doGet()。所以不必覆盖service()方法,只需覆盖想用的的do方法即可。当post请求时,doPost方法被调用。与POST请求相关的参数作为一个单独的HTTP请求从浏览器发送到服务器。当需要修改服务器的数据时,应该使用doPost()方法。 当一个客户通过HTML表单发出一个HTTPGET请求或直接请求一个URL时,doGet()方法被调用。。与GET请求相关的参数添加到URL的后面,并与这个请求一起发送。当不会修改服务器端的数据时,应该使用doGet()方法 - destory()方法:
estroy()方法仅执行一次,即在服务器停止且卸装servlet时执行该方法。
JSP的九大内置对象,四大作用域
- request 请求对象 类型 javax.servlet.ServletRequest 作用域 Request
- response 响应对象 类型 javax.servlet.SrvletResponse 作用域 Page
- pageContext 页面上下文对象 类型 javax.servlet.jsp.PageContext 作用域 Page
- session 会话对象 类型 javax.servlet.http.HttpSession 作用域 Session
- application 应用程序对象 类型 javax.servlet.ServletContext 作用域 Application
- out 输出对象 类型 javax.servlet.jsp.JspWriter 作用域 Page
- config 配置对象 类型 javax.servlet.ServletConfig 作用域 Page
- page 页面对象 类型 javax.lang.Object 作用域 Page
- exception 例外对象 类型 javax.lang.Throwable 作用域 page
详细参考:https://www.cnblogs.com/neal-xiang/p/6002237.html
四大作用域
JSP四大作用域分别为:page, request ,session, application 。
-
第一个作用域是page,他只在当前页面有效,也就是用户请求的页面有效,当当前页面关闭或转到其他页面时,page对象将在响应回馈给客户端后释放。
-
第二个作用域是request,他在当前请求中有效,request可以通过setAttribute()方法实现页面中的信息传递,也可以通过forward()方法进行页面间的跳转,需要注意的是request是转发不是重定向,转发相对于浏览器来说是透明的,也就是无论页面如何跳转,地址栏上显示的依旧是最初的地址。
-
第三个作用域是session,他在当前回话中有效。当一个台电脑上的同一浏览器对服务器进行多次访问时,在这多次访问之间传递的信息就是session作用域的范围。它从浏览器发出第一个HTTP请求即可认为会话开始,但是会话结束的时间是不确定的,因为在浏览器关闭时并不会通知服务器,一般Tomcat设置的默认时间为120分钟,也可以通过setMaxInactiveInterval(int)方法进行设置,或是通过invalidate()方法强制结束当前会话。
-
第四个作用域是application,他在所有的应用程序中都有效,也就是当服务器开始到服务器结束这段时间,application作用域中存储的数据都是有效的,同样可以通过setAttribute赋值和getAttribute取值。
线程问题
多线程
优点:
提高CPU的使用率,提高程序的工作效率
缺点:
大量线程会影响性能,因为CPU会在线程之间来回切换
可能存在线程安全问题或者是死锁问题
线程池
因为每个多线程在使用完成之后都会销毁,所以对于多线程来说,线程池采取线程复用,控制最大并发数,管理线程。
线程复用
每一个Thread都有一个start方法,当调用start方法之后,虚拟机会调用该类的run方法,那么该类的run方法就是调用Runnable对象的run方法,我们可以重写Thread类,在其start方法中添加不断循环调用传递过来的Runnable方法,这就是线程池的实现原理。
线程池的组成
1、线程池管理:用于创建并管理线程池
2、工作线程:线程池中的线程
3、任务接口:每个任务都必须实现的接口,用于工作线程调度其运行
4、任务队列:用于存放待处理的任务,提供一种缓冲机制
Http协议
session和cookie的区别
- cookie数据存放在客户的浏览器上,session数据放在服务器上。
- cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session。
- session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie。
- 单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。
- 可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中。
更多详细情况:https://www.cnblogs.com/8023-CHD/p/11067141.html
Http、Tcp、Udp区别
Http
http是一种超文本协议,而http每一次发送一次请求都会创建一条与服务器的tcp连接,并发送一个请求到服务器。
Tcp
tcp是机器之间连接用到的一种协议,可分为三个层面:网络层、传输层、应用层。Tcp面向连接,连接之前必须保证两端已连接,及三次握手
Tcp的三次握手
-
主机A向主机B发出连接请求数据包,这是第一次对话;
-
主机B向主机A发送同意连接和要求同步(同步就是两台主机一个在发送,一个在接收,协调工作)的数据包,这是第二次对话;
-
主机A再发出一个数据包确认主机B的要求同步,这是第三次对话。
Tcp的四次挥手
- 主机A向主机B发送断开请求,自己进入第一次半关闭状态
- 主机B向主机A回复确认,自身处于等待关闭状态,主机A收到后等待主机B向自己发起断开请求,自身第二次半关闭状态
- 主机B向主机A发起断开请求,自身进入半关闭状态
- 主机A接收到之后回复并进入等待,不管有没有收到回复,四分钟后都会进行断开,如果收到则立马断开
Udp
Udp属于面向非连接协议,不需要建立连接,直接把数据包传送过去
UDP和TCP的区别
UDP是面向非连接,效率高于TCP,但数据传输不安全,且传输数据量比较小。而TCP是面向连接,数据安全且可大量传输数据,但效率不如UDP
IO流
字节流和字符流
字节流和字符流的区别
以stream结尾的都是字节流,reader和writer结尾的是字符流
InputStream是所有字节输入流的父类,OutputStream是所有字节输出流的父类。
Reader是字符输入流的父类,Writer是字符输出流的父类。
区别:
字符流处理的单元为2个字节的Unicode字符,分别操作字符、字符数组或字符串,而字节流处理单元为1个字节,操作字节和字节数组。所以字符流是由Java虚拟机将字节转化为2个字节的Unicode字符为单位的字符而成的,所以它对多国语言支持性比较好!如果是音频文件、图片、歌曲,就用字节流好点 ,如果是关系到中文(文本)的,用字符流好点
事务
什么是事务
事务是数据库操作的最小单位,是作为单个逻辑单元的执行的一系列操作。这些操作作为整体去提交,要么都执行,要么不执行
事务的四个特性
- 原子性
事务中的操作,要么全做完,要么全部做完 - 隔离性
同一时间,只允许一个事务操作数据 - 持久性
事务完成之后,事务对数据库的所有操作都保存到数据库中 - 一致性
事务操作前后,数据库的完整性没有遭到破坏,比如A给B转钱,A钱少了,而B钱没多
事务并发问题
首先先搞清楚脏读、不可重复读、幻读这些东西
- 脏读
读取到另外一个事务回滚前的数据,比如B用一百块钱去买东西,花了五十,而A读取到此时B还剩五十,但B由于事务回滚没有执行成功,而B还有一百。而A读取到的B还剩五十就是脏数据。 - 不可重复读
在不同时间,读取到的数据不同。比如B用一百块钱去买东西,此时A读取到B剩余一百,之后B买东西花掉五十,此时A由读取到B剩余五十。 - 幻读
两次读取到的对数据的计数不同,比如现查询有三个用户,但增加或者删除一个用户之后,查询出来的结果跟之前的不同。
-总结
不可重读侧重于修改数据所形成的的两次数据内容不同,而幻读侧重于增删。
事务隔离级别 | 脏读 | 不可重复读 | 幻读 | 数据库默认级别 |
---|---|---|---|---|
读未提交(read-uncommitted) | 是 | 是 | 是 | |
读已提交(read-committed) | 否 | 是 | 是 | Orcale、SqlServer |
可重复读 (repeatable-read) | 否 | 否 | 是 | Mysql |
串行化(serializable) | 否 | 否 | 否 |
Oracle
Oracle中Truncate和Delete的区别
简单来说Delete用来删除数据库中指定范围内的数据,即where后面所指定的数据,且可以事务回滚。Truncate删除表中所有数据,且不可以事务回滚
Oracle中常用的函数
AVG 取平均值
SUM 求和
MIN/MAX 最小最大值
COUNT 数据统计
NVL(X,Value)如果X为空则返回Value,不为空返回X
TO_CHAR 把当前日期和数字转换为指定格式的字符串
ROUND 四舍五入
TRUNC 直接截取,不四舍五入
Redis
redis持久化
众所周知,redis是内存数据,把数据存储到内存中,读写效率增加,但如果Redis所在的服务器宕机,则数据将全部丢失,所以需要通过AOF和RDB将数据持久化到硬盘中。
- redis默认开启RDB(快照)持久化,在指定时间内执行,执行指定次数的写操作,将数据持久化到硬盘中
- RDB适合大规模的数据恢复,但它的数据一致性和完整性较差
- redis需要手动开启AOF持久化,AOF每秒钟读取写操作日志到AOF文件上
- AOF的完整性比RDB高,但由于内容多,数据的恢复效率较低
redis支持的数据类型
String类型,值为字符串,可以为简单字符串,复杂字符串(XMl,Json),数字(整形,字符),二进制(图片,音频,视频)
Hash类型,其中的值为键值对
set类型,值存的无序且不重复,
zset类型,加强set类型,值仍不能重复,但是存值的时候会带一个分数,通过分数来排序
list类型,值有序可重复
sql知识
union和union all的区别
union 是可以对两个结果集进行并集操作,不包括重复行,同时进行默认规则的排序
union all对两个结果集进行并集操作,,包括结果集,不进行排序
数据库的三范式
第一范式:列不可分
第二范式:在第一范式基础上,一张表存在组合索引的时候,其他非主键字段不能部分依赖
第三范式:基于第二范式,除主键外,其他字段必须依赖主键
一些关于sql的知识,下面链接内容比较全面
https://blog.csdn.net/lizhen1114/article/details/79076447
关于索引的问题
https://www.cnblogs.com/heqiyoujing/p/11229260.html
sql语句
dept表结构
emp表结构
外键链接
查找员工表中编号(Code)重复的员工记录,输出列:“员工ID,员工编号Code、员工姓名”
select ID ,`Name`,`Code`
from emp
where Code in
(select * from emp GROUP BY `Code` HAVING COUNT(Code)>1)
写出有十个员工以上的部门及员工数量,输出:部门ID、员工部门、员工数
select d.ID,d.`Name`,COUNT(emp.`Code`)
from emp, dept d
where emp.DeptID=d.ID and (select COUNT(emp.`Code`) from emp)>10
写出全部员工单(包含未分配部门的) 输出列:员工ID,员工名称,员工部门
select emp.`Name`,emp.`Code`,emp.DeptID
from emp LEFT JOIN dept on
emp.DeptID=dept.ID