一、Java
1、请实现一个单例类,提示:如何保证线程安全?
public class MySingleton {
//内部类
private static class MySingletonHandler{
private static MySingleton instance = new MySingleton();
}
private MySingleton(){}
public static MySingleton getInstance() {
return MySingletonHandler.instance;
}
}
2、请写一个User的纯数据类,有id与name字段。写完后,请简述此时需要在User类中添加其它字段时,有哪些需要注意的地方。
/*当需要修改时
* 1.作为entity,因保证安全,则修饰符为private
* 2.修改构造方法
* */
public class User {
private int id;
private String name;
public User(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
3、请实现一个观察者模式observer pattern。
修改1.0
被观察者
public abstract class Observer {
public abstract void update();
}
被观察者进一步实现
public class ConcreateObserver extends Observer {
private String name;
private ConcreateSubject subject;
private String state;
public ConcreateObserver(String name, ConcreateSubject subject) {
this.name = name;
this.subject = subject;
}
@Override
public void update() {
state = subject.getState();
System.out.println("running");
}
}
观察者
public class Subject {
private List<Observer> list = new ArrayList<>();
public void add(Observer o) {
list.add(o);
}
public void remove(Observer o) {
list.remove(o);
}
public void toNotify() {
for (Observer o:list) {
o.update();
}
}
}
public class ConcreateSubject extends Subject{
String state;
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
执行
public class Main {
public static void main(String[] args) {
ConcreateSubject c = new ConcreateSubject();
c.add(new ConcreateObserver("liao", c));
c.add(new ConcreateObserver("chuan", c));
c.setState("boss coming");
c.toNotify();
}
}
补充1.
![](https://img.haomeiwen.com/i2331003/cb149fcfc9523cd7.png)
4、请简述你对hashcode, equals 与==的理解。
对于hashcode与equals()
1.是Object的方法.
2.使用equals判断字符串内容是否相等.
3.特别的,对于String类型,可以生成特定的hash,在hashmap中插入String内容,后期跟据equals与hashcode进行碰撞冲突检测
4.能被重写
对于==
1.比较地址
2.运算符
补充1
equals与hashcode属于object的方法,而hashcode是native字段修饰,所以是原生方法,即是使用c/cpp写成,而equals在object中是比较地址
补充2
hashcode是为了比较的高效性存在,当存在两个比较值,若hashcode不同,则equals必为false,若hashcode相同,则equals可为true可为false,hashcode就像存储的段地址一样,并不是精确的地址
补充3
在java中摒弃了运算符重载
5、请简述在你所使用的框架中,数据库操作时添加@Transactional会产生什么效果,工作原理是什么。
效果:
1.事务传播等很多重要方面可以自动处理
2.跨越多个事务使用
工作原理:
1.EntityManager Proxy本身
2.事务的切面
3.事务管理器
补充1
@Transactional在JPA中有其定义,但诸如spring,hibenate对于其接口定义的不满足,所有重新继承并实现新的功能,这样在使用过程中更加方便.所有的orm面向对象框架都会遵循jpa规范.这是oracle的野心所在,想要将所有的持久层框架的规范统一,但在后期三方框架拓展过程中或用户使用过程中,不能满足于当前规范,所以有spring的@Transactional或者hibenate的@Transactional.
补充2
@Transactional是指对数据库事务属性的设置,比如只读,可读可写,可重复读,读已提交,读未提交
补充3
在数据库中为了效率高效,是多个事务共同工作,所以涉及到并发操作,也就是悲观锁,乐观锁,死锁的使用
补充4.数据库相关锁有哪些?
1.行锁:锁住相应的记录
2.表锁:锁住整张表
3.页锁:
4.排他写锁:若事务A对数据对象加上X锁,则只允许A进行操作,其他事务不能操作
5.共享锁:若事务A对数据对象加上S锁,则其他事务也只能加S锁,不能加X锁
6.悲观锁(使用for update使用mysql的悲观锁机制,在之前关闭autocommit,之后使用事务)
7.乐观锁
8.死锁:产生死锁的四个条件
(1)互斥条件:指进程对所分配到的资源进行排它性使用,即在一段时间内某资源只由一个进程占用。如果此时还有其它进程请求资源,则请求者只能等待,直至占有资源的进程用毕释放.
(2)请求和保持条件:指进程已经保持至少一个资源,但又提出了新的资源请求,而该资源已被其它进程占有,此时请求进程阻塞,但又对自己已获得的其它资源保持不放
(3)不剥夺条件:指进程已获得的资源,在未使用完之前,不能被剥夺,只能在使用完时由自己释放
(4)环路等待条件:指在发生死锁时,必然存在一个进程——资源的环形链,即进程集合{P0,P1,P2,···,Pn}中的P0正在等待一个P1占用的资源;P1正在等待P2占用的资源,……,Pn正在等待已被P0占用的资源
补充5
虚读:事务1读取数据,之后事务2修改数据,事务1再次读取发现数据和之前不一致
幻读:事务1对全部数据进行修改,事务2插入一条数据,事务1发现还有未修改的数据,就像发生幻觉一样
脏读:事务1读取某个数据,而事务2修改了数据但还未提交,导致事务1读取了脏数据
二、网络工程、安全
6、请简述你对git merge与git rebase的理解。
1.merge只是合并另外一个分支的内容
2.rebase也合并另外一个分支的内容,但是会把本分支的commits顶到最顶端
7、请描述从浏览器地址栏输入www.163.com以后浏览器和各类型服务器的相关响应事件。
1.dns解析域名
2.tcp封装数据
3.添加源和目的端口
4.通过路由器转发
5.得到mac地址,到达服务器.
补充1
浏览器首先查找本地hosts文件,是否有该域名与ip的索引关系,如果没有,才通过dns到外网查找.
补充2
三次握手:一次握手客户发送信息段,syn=1(synchronous建立联机),Sequence Number为x,客户端进入SYN_SEND状态,二次握手syn=1,ack+1,Sequence Number=y,进入SYN_RECEIVED状态,三次握手客户端收到ack=y+1,两端进入ESTABLISHED(已连接状态)
补充3
四次挥手,第一次发送fin信号,二次确认接收发送ack=1,并进入wait状态,三次发送fin,并进入LASK_ACK状态,四次另一端接收发送确认,并进入time_out,若没有再来请求,则关闭
8、请简述项目中优化数据库查询的方法。
1.减少select *的使用,尽量指明字段
2.尽量避免在 where 子句中对字段进行 null 值判断,尽量避免在 where 子句中使用!=或<>操作符(因为这样会数据库会放弃索引,而全表扫描)
4.尽量避免在where子句中对字段进行函数操作
补充1
能使用数字的字段尽量使用字段,如果使用字符串,在查询时会逐个字符比较,增加查询开销
补充2.强制使用某个索引查询,select * from table force index(PRI) limit 2;
9、请说明CSRF攻击的例子,以及危害,如何防范?
1.例子:欺骗用户的浏览器发送HTTP请求
2.危害,盗取密码等违法行为
3.将持久化的授权方法(例如cookie)切换为瞬时的授权方法
补充1
csrf与xss不同之处在于,csrf的攻击动作是由用户自己完成,而xss是攻击者发现漏洞,于是构造请求,由攻击者亲自执行,在log中容易被发现
三、数据结构、算法
10、请填写下列容器实现各操作的时间复杂度,及内部数据结构(若不支持某操作,请标记).
内部数据结构 随机Index/Key取值 随机Index/Key插入 随机Index/Key删除 追加元素
ArrayList 数组 O(1) O(n) O(n) O(1)
LinkedList 链表 O(n) O(n) O(n) O(1)
TreeMap 二叉搜索树 O(log(n)) O(log(n)) O(log(n)) O(log(n))
HashMap 数组 O(1) O(1) O(1) O(1)
PriorityQueue 堆 O(n) O(log(n)) O(n) O(log(n))
LinkedHashMap 链表 O(n) O(1) O(1) O(1)
补充1.treemap底层数据结构二叉搜索树,也就是红黑树,特点和相关操作如下:
- 基本特点
- 每个节点要么是红要么是黑
- 跟节点是黑
- 树叶节点是黑
- 节点为红,则两个孩子为黑
- 对任意叶节点,每条路径都包含相同数目的黑节点
![](https://img.haomeiwen.com/i2331003/be68eb0c2da42543.gif)
![](https://img.haomeiwen.com/i2331003/bce8943a6aaf6051.gif)
补充2
因为hashtable线程同步,同一时刻单线程处理,所以时间比hashmap慢
补充3.linkedlist
- 双链表机制(可以直接访问前一个节点,linux内核中的实现)
11、给出一个链表,比如链表1→2→3→4→5→6,则翻转后6→5→4→3→2→1,请用程序实现。
public class Solution {
public ListNode ReverseList(ListNode head) {
if(head==null || head.next==null){
return head;
}
//递归
ListNode start = ReverseList(head.next);
head.next.next = head;
head.next = null;
//返回尾节点
return start;
}
}
12、已知函数 rand3(), 能等概率地返回 [0, 2] 区间的整数。
请依赖 rand3()设计一个能等概率返回 [0, 4] 区间整数的函数 rand5()。
public int rand5(){
int r;
do{
r = 2*rand3() + rand3();
} while(r >= 5);
return r;
}
补充1.
public int rand5(){
int r;
do{
r = 3*rand3() + rand3();
} while(r >= 5);
return r;
}
居然把其中的rand3()写成rand1(),简直是不能原谅自己.
13、矩阵置零
给定一个M*N的int类型矩阵, 如果一个元素为0,则把其所在的行列的所有元素全部置为 0(无需处理输入输出)。
请原地(in-place)完成。
*原地完成: 除给定数据外,申请额外空间的复杂度为O(1)。
例:
Input:
1 2 6 0
2 1 0 1
4 5 3 1
Output:
0 0 0 0
0 0 0 0
4 5 0 0
14、矩阵搜索
给定一个0,1矩阵M1, 求它在另外一个大0, 1矩阵M2中出现了几次(无需处理输入输出),例如下
Input:
M1 = 1 1 M2 = 0 0 0 1 1
1 1 1 0 1 1 1
1 0 1 1 1
Output:
3
网友评论