记面试题。。。

20191030 福建泛微科技 笔试题

简答题

1.Java 的泛型是什么?有什么好处和优点?JDK 不同版本的泛型有什么区别? 

泛型是 Java SE 1.5 的新特性,泛型的本质是参数化类型,这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。在 Java SE 1.5 之前没有泛型的情况的下只能通过对类型 Object 的引用来实现参数的任意化,其带来的缺点是要做显式强制类型转换,而这种强制转换编译期是不做检查的,容易把问题留到运行时,所以 泛型的好处是在编译时检查类型安全,并且所有的强制转换都是自动和隐式的,提高了代码的重用率,避免在运行时出现 ClassCastException。

JDK 1.5 引入了泛型来允许强类型在编译时进行类型检查;JDK 1.7 泛型实例化类型具备了自动推断能力,譬如 List<String> list = new ArrayList<String>(); 可以写成 List<String> llist = new ArrayList<>(); 了,JDK 具备自动推断能力。下面几种写法可以说是不同版本的兼容性了。

2.什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。

什么是序列化,怎么序列化,为什么序列化,反序列化会遇到什么问题,如何解决。_老周聊架构的博客-CSDN博客_序列化

概念

序列化:把对象转换为字节序列的过程称为对象的序列化。
反序列化:把字节序列恢复为对象的过程称为对象的反序列化。

什么情况下需要序列化

当你想把的内存中的对象状态保存到一个文件中或者数据库中时候;
当你想用套接字在网络上传送对象的时候;
当你想通过RMI传输对象的时候;

反序列化问题

Java的序列化机制是通过在运行时判断类的serialVersionUID来验证版本一致性的。在进行反序列化时,JVM会把传来的字节流中的serialVersionUID与本地相应实体(类)的serialVersionUID进行比较,如果相同就认为是一致的,可以进行反序列化,否则就会出现序列化版本不一致的异常。(InvalidCastException)

3.table显示n条记录,每三行换一次颜色,即1,2,3用红色字体,4,5,6用绿色字体,7,8,9用红色字体

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <script>
        window.onload = function () {
            var tr = document.getElementById("tb").getElementsByTagName("tr");
            for (let i = 0; i < tr.length; i++) {
                var n = parseInt(i / 3);
                if (n % 2 == 0) {
                    tr[i].style.backgroundColor = "red";
                } else {
                    tr[i].style.backgroundColor = "green";
                }
            }
        }
    </script>
</head>

<body>
    <table id="tb" border="1">
        <tr>
            <td>1</td>
        </tr>
        <tr>
            <td>2</td>
        </tr>
        <tr>
            <td>3</td>
        </tr>
        <tr>
            <td>4</td>
        </tr>
        <tr>
            <td>5</td>
        </tr>
        <tr>
            <td>6</td>
        </tr>
        <tr>
            <td>7</td>
        </tr>
        <tr>
            <td>8</td>
        </tr>
        <tr>
            <td>9</td>
        </tr>
        <tr>
            <td>10</td>
        </tr>
        <tr>
            <td>11</td>
        </tr>
        <tr>
            <td>12</td>
        </tr>
        <tr>
            <td>13</td>
        </tr>
        <tr>
            <td>14</td>
        </tr>
        <tr>
            <td>15</td>
        </tr>
        <tr>
            <td>16</td>
        </tr>
        <tr>
            <td>17</td>
        </tr>
        <tr>
            <td>18</td>
        </tr>
    </table>
</body>

</html>

4.有一张tree表

1.写一个SQL查询"孙节点1”, 查询祖先节点。
通过三张表自关联表查询,第一张祖先节点表,第二张父节点表,第三章孙节点表

SELECT
	*
FROM
	tree t1
	LEFT JOIN tree t2
	JOIN tree t3 ON t2.id = t3.pid ON t1.id = t2.pid 
WHERE
	t3.`name` = '孙节点1';

2.写一个sql查询"父节点1",遍历子孙节点。
 

SELECT
	* 
FROM
	tree t1
	LEFT JOIN tree t2 ON t1.id = t2.pid 
WHERE
	t1.`name` = '父节点1';

2020.2.27 福建新意科技 笔试题

单选题

A Map不是

5.全错  D抽象类的抽象方法不可以有方法体,但是非抽象方法可以有B不可以改变访问权限 A接口可以有静态变量

7.D 不必须,运行时异常(runtime exceptions),需要程序员自己分析代码决定是否捕获和处理,比如 空指针,被0除

问答题

1.下面的代码输出是?

public class Parent {
    public void method() {
        System.out.println("parent");
    }

    public static void smethod() {
        System.out.println("parent");
    }
}

public class Child extends Parent {
    public void method() {
        System.out.println("child");
    }

    public static void smethod() {
        System.out.println("child");
    }
}

public class Test {
    public static void print(String[] args) {
        Child c = new Child();
        Parent p = (Parent) c;
        p.method();
        p.smethod();
    }
}
child
parent
不可以重载父类的static方法,如果没有指向父类直接调用smethod,那么就会使输出child
Child c = new Child();
c.smethod();//child

2. 下面代码中两处console输出什么? 为什么?

var User = {
    count: 1,
    getCount: function() {
        return this.count;
    }
};
console.log(User.getCount());
var func = User.getCount;
console.log(func());
1
undefined
<!-- 一般来说,this指向的其实就是:包含this的函数(对象)的父元素; -->
var User={
  data:this,//包含这个this的是User对象,其父元素是window,故此时this指向window对象
  count:1,
  getCount:function(){
  return this.count//包含这个this的是getCount方法,其父元素是User对象,故此时this指向User对象
  }
}
console.log(User.getCount());//1
var fuc=User.getCount;//将对象User的getCount方法赋值给变量fuc,相当于:fuc=function(){return this.count}
console.log(fuc);/*ƒ (){
  return this.count//包含这个this的是getCount方法,其父元素是User对象,故此时this指向User对象
  }*/
console.log(fuc());//undefined  此时fuc对象是没有count属性的,故此this.count是不存在的,返回undefined
console.log(User.data);//Window 对象

3.

去除字符串中的转义符\n
输入:一个带转义字符’\ n’的字符串
要求:删除转义字符’\ n’和它前面的字符,如果遇到多个连续的’\n’,则删除相同数量的转义字符和前面的字符
输出:最终的结果字符串
举例:输入”abc\n\nd\n\nnghi”,期望输出”nghi”
String s = "abc123梅丽娜W:**LDM<\n\nd\n\nngh\ni";
Pattern p = Pattern.compile("([^\"]+)(?=\n{2,})|\n");
Matcher matcher = p.matcher(s);
s = matcher.replaceAll("");
  • ([^\"]+):任意字符
  • (?=\n{2,}):至少俩个\n前面的字符
  • |:或

2020.3.4 新意科技 技术经理电话面试

前端问题

绝对定位和相对定位区别

Absolution:元素会脱离文档流,定位是相对于离它最近的且不是static定位的父元素而言,若该元素没有设置宽度,则宽度由元素里面的内容决定,且宽度不会影响父元素,定位为absolution后,原来的位置相当于是空的,下面的的元素会来占据。

Relative:元素仍处于文档流中,定位是相对于原本自身的位置,若没有设置宽度,则宽度为父元素的宽度,该元素的大小会影响父元素的大小。

左浮动,右浮动

元素的居左居右问题,都是相对于父元素进行的浮动,确切来说就是在这个元素的左边或者右边位置,不再处于文档流中,所以它不占据空间。

穿透

真前端人员问题,不想了解

请求转发,重定向区别

闭包 

看这篇,「每日一题」JS 中的闭包是什么? - 知乎

在函数内部可以访问外部变量,可以达到隐藏变量的目的

function foo(){
  var local = 1
  function bar(){
    local++
    return local
  }
  return bar
}

var func = foo()
func()

这里面确实有闭包,local 变量和 bar 函数就组成了一个闭包(Closure)。

为什么要函数套函数呢?

是因为需要局部变量,所以才把 local 放在一个函数里,如果不把 local 放在一个函数里,local 就是一个全局变量了,达不到使用闭包的目的——隐藏变量(等会会讲)。

这也是为什么我上面要说「运行在一个立即执行函数中」。

有些人看到「闭包」这个名字,就一定觉得要用什么包起来才行。其实这是翻译问题,闭包的原文是 Closure,跟「包」没有任何关系。

所以函数套函数只是为了造出一个局部变量,跟闭包无关。

数据库

怎么进行 行专列?

行转列一般是用于一对多情况,多的那就是要转成列,比如一个学生多门科目的成绩

创建表

DROP TABLE IF EXISTS `stu_grade`;
CREATE TABLE `stu_grade`  (
  `ID` int(0) NOT NULL AUTO_INCREMENT,
  `S_NAME` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `COURSE` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `SCORE` float NULL DEFAULT 0,
  PRIMARY KEY (`ID`) USING BTREE
) 

INSERT INTO `stu_grade` VALUES (1, '张三', '数学', 34);
INSERT INTO `stu_grade` VALUES (2, '张三', '语文', 58);
INSERT INTO `stu_grade` VALUES (3, '张三', '英语', 58);
INSERT INTO `stu_grade` VALUES (4, '李四', '数学', 45);
INSERT INTO `stu_grade` VALUES (5, '李四', '语文', 87);
INSERT INTO `stu_grade` VALUES (6, '李四', '英语', 45);
INSERT INTO `stu_grade` VALUES (7, '王五', '数学', 76);
INSERT INTO `stu_grade` VALUES (8, '王五', '语文', 34);
INSERT INTO `stu_grade` VALUES (9, '王五', '英语', 89);

 转成这样

1.我们来一步一步做,先通过if语句,一行一行的查,是否符合条件,如果是数学就显示分数,如果不是就显示0,所以会出现下图的分数为0情况。

SELECT
    S_NAME,
    IF( COURSE = '数学', SCORE, 0 ) 数学,
    IF( COURSE = '语文', SCORE, 0 ) 语文,
    IF( COURSE = '英语', SCORE, 0 ) 英语 
FROM
	stu_grade

2.我们要去除0,并且一个人不会出现三次,而是每个人只出现一次 ,所以需要GROUP BY进行分组,但是只加了分组发现,只会选取每组第一行。

SELECT
    S_NAME,
    IF( COURSE = '数学', SCORE, 0 ) 数学,
    IF( COURSE = '语文', SCORE, 0 ) 语文,
    IF( COURSE = '英语', SCORE, 0 ) 英语 
FROM
	stu_grade
GROUP BY
	S_NAME

3. 所以要对分组完的表进行筛选,选择分数最大的那个,加MAX ✔

SELECT
	S_NAME,
	MAX(
	IF
	( COURSE = '数学', SCORE, 0 )) 数学,
	MAX(
	IF
	( COURSE = '语文', SCORE, 0 )) 语文,
	MAX(
	IF
	( COURSE = '英语', SCORE, 0 )) 英语 
FROM
	stu_grade 
GROUP BY
	S_NAME

4.还有一种办法使用max+case语句 ✔

SELECT
	S_NAME,
	MAX( CASE COURSE WHEN '数学' THEN SCORE ELSE 0 END ) 数学,
	MAX( CASE COURSE WHEN '语文' THEN SCORE ELSE 0 END ) 语文,
	MAX( CASE COURSE WHEN '英语' THEN SCORE ELSE 0 END ) 英语 
FROM
	stu_grade 
GROUP BY
	S_NAME;

列转行

DROP TABLE IF EXISTS `stu_detail`;
CREATE TABLE `stu_detail`  (
  `ID` int(0) NOT NULL AUTO_INCREMENT,
  `S_NAME` varchar(20) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
  `数学` int(0) NULL DEFAULT NULL,
  `语文` int(0) NULL DEFAULT NULL,
  `英语` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`ID`) USING BTREE
) 

INSERT INTO `stu_detail` VALUES (1, '张三', 34, 58, 58);
INSERT INTO `stu_detail` VALUES (2, '李四', 45, 87, 45);
INSERT INTO `stu_detail` VALUES (3, '王五', 76, 34, 89);

	SELECT S_NAME,'语文' COURSE ,语文 SCORE from stu_detail
	union all 
	SELECT S_NAME,'数学' COURSE ,数学 SCORE from stu_detail
	union all 
	SELECT S_NAME,'英语' COURSE ,英语 SCORE from stu_detail

java

1.hashmap底层结构说一下

hashmap原理前置知识学习_Fire_Sky_Ho的博客-CSDN博客

2.多线程引发的问题

1.对于共享数据的修改读取的脏读等,并发下的主内存和工作内存之间的变量的不可见性,volatile关键字可解决。

2.死锁问题

解决办法:破坏不抢占条件
如果一个线程已经获取到了一些锁,那么在这个线程释放锁之前这些锁是不会被强制抢占的。但是为了防止死锁的发生,我们可以选择让线程在获取后续的锁失败时主动放弃自己已经持有的锁并在之后重试整个任务,这样其他等待这些锁的线程就可以继续执行了。

3.springmvc流程

Spring MVC流程简单说明_Fire_Sky_Ho的博客-CSDN博客

2020.12.18 电话面试

类加载过程

1.加载:将class字节码文件加载到内存中,在堆中生成一个Class类

2.检查:检查加载的class文件的正确性;

3.准备:给类中的静态变量分配内存空间,并赋默认值;

   注意:

  1. 只对static修饰的静态变量进行内存分配、赋默认值(如0、0L、null、false等)。
  2. 对final的静态字面值常量直接赋初值(赋初值不是赋默认值,如果不是字面值静态常量,那么会和静态变量一样赋默认值)。

4.解析:虚拟机将常量池中的符号引用替换成直接引用的过程。符号引用就理解为一个标示,而在直接引用直接指向内存中的地址;

5.初始化:对静态变量和静态代码块执行初始化工作。如下

private static String x="123";
static{ x="123"; } 

重载重写区别

  • 重载:关键字overload,方法名相同,方法参数个数和类型不一样,返回类型可以不同,前提是方法参数不一致,不然系统不懂要调用哪个方法,如下图会报错。 

  • 重写:也叫方法覆盖,关键字override,相对于类继承而言,重写的方法名,返回类型,参数个数,参数类型都要求和父类一样

MySql数据库优化

  1. from中记录条数和列名最少的表,写在最后,因为数据库的解析器按照从右到左的顺序处理FROM子句中的表名,inner join,无所谓,left join 把大表放在后边,right join把大表放在前面,尽量小表驱动大表,为啥?MySQL高级知识(十六)——小表驱动大表
  2. 避免使用*
  3. 多使用内部函数
  4. 如果表或列的名称太长了,使用一些简短的别名
  5. 添加索引:普通索引,唯一索引,主键索引,组合索引,全文索引

ArrayList原理

  • ArrayList底层是由动态数组实现,默认为10的长度。
  • 如果当添加的元素超过当前数组的长度时,它会新创建一个数组,长度为当前数组的1.5倍,然后将当前数组的元素复制到新的数组,当前数组的内存被释放。

LinkedHashMap

LinkedHashMap是继承于HashMap,是基于HashMap和双向链表来实现的

Maven作用,镜像

作用:用于构建和管理Java相关项目的工具,便于统一维护jar包

镜像:配置镜像地址后,任何对于中央仓库的请求都会被拦截,然后转到该镜像。

           注意:镜像仓库完全屏蔽了被镜像仓库,当镜像仓库不稳定或者停止服务的时候,Maven仍将无法访问被镜像仓库,因而将无法下载构件。

Web项目发布到Tomcat步骤

war包方式:将项目打成war包,放到Tomcat的webapps目录下,然后启动tomcat。

Jar包方式:将项目打成jar包,执行java -jar 包名。

GC-----Garbage Collection(垃圾回收)

1、一个人(对象)出来(new 出来)后会在Eden Space(伊甸园)无忧无虑的生活,直到GC到来打破了他们平静的生活。GC会逐一问清楚每个对象的情况,有没有钱(此对象的引用)啊,因为GC想赚钱呀,有钱的才可以敲诈嘛。然后富人就会进入Survivor Space(幸存者区),穷人的就直接kill掉。

2、并不是进入Survivor Space(幸存者区)后就保证人身是安全的,但至少可以活段时间。GC会定期(可以自定义)会对这些人进行敲诈,亿万富翁每次都给钱,GC很满意,就让其进入了Genured Gen(养老区)。万元户经不住几次敲诈就没钱了,GC看没有啥价值啦,就直接kill掉了。

3、进入到养老区的人基本就可以保证人身安全啦,但是亿万富豪有的也会挥霍成穷光蛋,只要钱没了,GC还是kill掉。

分区的目的:新生区由于对象产生的比较多并且大都是朝生夕灭的,所以直接采用标记-清理算法。而养老区生命力很强,则采用复制算法,针对不同情况使用不同算法。

Java堆是被所有线程共享的一块内存区域,所有对象实例和数组都在堆上进行内存分配。为了进行高效的垃圾回收,虚拟机把堆内存划分成1/3的新生代2/3的老年代2个区域。

新生代转移到老年代:存活对象会反复在两个Survivor移动(两个是为了防止内存碎片化),当对象从Eden移动到Survivor或者在Survivor之间移动时,对象的GC年龄自动累加,当GC年龄超过默认阈值15时,会将该对象移动到老年代;Eden:s0:s1=8:1:1。

永久代:存在在于JDK1.8以下,方法区和永久代的关系很像Java中接口和类的关系,类实现了接口,而永久代就是HotSpot虚拟机对虚拟机规范中方法区的一种实现方式。

元空间:JDK1.8及以上已经取消了永久代,改为元空间,类的元信息被存储在元空间中称为元空间,使用本地内存。

注意:元空间和永久代都是方法区的具体实现,方法区由元空间(类信息)和堆实现(常量池、静态变量) ,字符串常量在堆内存,类的元数据在本地内存。参考:Java 字符串常量池到底是在PermGen方法区、是在heap堆里面、还是在Metaspace 元空间里面呢?

下面的图是我根据各种文章推断出来的,不一定正确。

Java8的JVM内存结构

怎么判断对象是否可以被回收?是否存活?

  • 引用计数器:在对象上添加一个引用计数器,每当有一个对象引用它时,计数器加1,当使用完该对象时,计数器减1,计数器值为0的对象表示不可能再被使用。
  • 可达性分析法:从GC Roots开始向下搜索,搜索所走过的路径称为引用链。当一个对象到GC Roots没有任何引用链相连时,则证明此对象是可以被回收的。

GC root有几下种:

  • 由系统类加载器(system class loader)加载的对象
  • 活着的线程
  • ......

Minor GC,Major GC,Full GC

Minor GC:当新生代Eden无法为新生对象分配内存空间的时候区满了会触发

Major GC:清理老年代

Full GC:清理年轻代、老年代、元空间

不管什么GC,都会发生stop-the-world(暂停所有其他的线程)。

垃圾回收算法

图文介绍文章 Java 垃圾回收机制与几种垃圾回收算法

  • 标记清除算法:标记无用对象,然后进行清除回收。缺点:效率不高,无法清除垃圾碎片。
  • 标记整理算法:标记无用对象,让所有存活的对象都向一端移动,然后直接清除掉端边界以外的内存。
  • 复制算法:按照容量划分二个大小相等的内存区域,当一块用完的时候将活着的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。缺点:内存使用率不高,只有原来的一-半。
  • 分代算法:根据对象存活周期的不同将内存划分为几块,一般是新生代和老年代,新生代基本采用复制算法,老年代采用标记整理算法。

GC时对象地址变了,hashCode保持不变

hashcode会保存下来

GC时对象地址变了,hashCode如何保持不变?

垃圾回收器

吞吐量:指在应用程序的生命周期内,应用程序所花费的时间和系统总运行时间的比值。系统总运行时间=应用程序耗时+GC 耗时。如果系统运行了 100min,GC 耗时 1min,那么系统的吞吐量就是 (100-1)/100=99%。

停顿时间:指垃圾回收器正在运行时,应用程序的暂停时间。对于独占回收器而言,停顿时间可能会比较长。使用并发的回收器时,由于垃圾回收器和应用程序交替运行,程序的停顿时间会变短,但是,由于其效率很可能不如独占垃圾回收器,故系统的吞吐量可能会较低。

并行收集:指多条垃圾收集线程并行工作,但此时用户线程仍处于等待状态。

并发收集:指用户线程与垃圾收集线程同时工作(不一定是并行的可能会交替执行)。用户程序在继续运行,而垃圾收集程序运行在另一个CPU上。

Serial:最早的单线程串行垃圾回收器。
Serial Old:Serial 垃圾回收器的老年版本,同样也是单线程的,可以作为CMS垃圾回收器的备选预案。
ParNew:是Serial的多线程版本。
Parallel:和ParNew收集器类似是多线程的,但Parallel是吞吐量优先的收集器,可以牺牲等待时间换取系统的吞吐量,复制算法。
Parallel Old:是Parallel老生代版本,Parallel Old使用的是标记整理的内存回收算法。
CMS:牺牲吞吐量为代价获得最短停顿时间为目标的收集器,非常适用B/S系统,标记清除算法。

    缺点:

  • 无法处理浮动垃圾,可能出现Concurrent Model Failure失败而导致另一次Full GC的产生。
  • 因为采用标记-清除算法所以会存在空间碎片的问题,导致大对象无法分配空间,不得不提前触发一次Full GC。

G1:兼顾吞吐量和停顿时间的GC实现,是JDK 9以后的默认GC选项。

串行垃圾回收器并行垃圾回收器并行并发
新生代SerialParNew,ParallelG1
老年代Serial OldParallel Old,CMS

这篇不错:Jvm垃圾回收器(终结篇)

2021.1.11 广西博繁软件 笔试+面试

String、StringBuffer、StringBuilder区别

  • String:声明的是不可变的对象,每次操作都会生成新的String 对象,然后将指针指向新的String 对象,直接赋值(String i="a")分配到常量池中,new赋值(String i=ne w String("a"))分配到堆中
  • StringBuffer,StringBuilder:可以在原有对象的基础,上进行操作,所以在经常改变字符串内容的情况下最好不要使用String。

==和equals的区别

==

  • 基本类型:比较的是值是否相同;
  • 引用类型:比较的是引|用是否相同;

equals:equals本质上就是==,只不过String和Integer等重写了equals方法,把它变成了值比较,两个类使用A.eqauls(B),比较的也是地址

增加和删除数据时,为什么LinkedList通常比ArrayList快

LinkedList只需要只需要改变节点引用就行,ArrayList对需要增删的节点之后的数据都需要进行移动

接口和抽象类区别

  1. 抽象类可以实现非抽象方法体,接口不可以实现方法
  2. 接口里定义的变量只能是公共的静态的常量,抽象类中的变量是普通变量
  3. 接口多实现,类单继承

Servle的init ()destroy() 什么时候进行

Servlet 初始化后调用 init () 方法,Servlet 销毁前调用 destroy() 方法。

死锁是什么?怎么解除?预防?

概念:多个进程在运行过程中因争夺资源而造成的一种僵局

预防:

  1. 全都按顺序获得锁
  2. 加入等待时间
  3. 尽量不要嵌套使用锁

解除:结束进程

HashMap、LinkedHashMap和TreeMap使用场景

LinkedHashMap和TreeMap:进行有序遍历使用

HashMap:插入、删除、定位

JSP servlet关系

JSP引擎先把JSP程序转换成servlet代码

子网掩码

用来划分IP地址中哪一部分是网络号,哪一部分是机器号

2021.1.21 广西锡祥科技

token怎么生成,在拦截器里怎么解析,存在哪,怎么加密

还是不太懂,还是得去写代码了解

MD5使用详解

漫画趣解MD5算法

HTTPS的加密原理

多态的存在有三个必要条件

继承,方法重写,父类引用指向子类对象。

TCP/IP网络模型,HTTP协议在哪层

模型:

  1. 数据链路层:负责封装和解封装IP报文,发送和接受ARP/RARP报文等。
  2. 网络层:负责路由以及把分组报文发送给目标网络或主机。
  3. 传输层:负责对报文进行分组和重组,并以TCP或UDP协议格式封装报文。
  4. 应用层:负责向用户提供应用程序,比如HTTP、FTP、Telnet、DNS、SMTP等。

redis宕机怎么办

哨兵模式,主从切换

使用Redis的持久化机制,第一种是RDB快照,第二种是AOF日志。快照是一次全量备份,将内存中的数据集快照写入磁盘;AOF日志是连续的增量备份,以日志的形式记录服务器所处理的每一个写、删除操作。

Nginx作用

反向代理,负载均衡,动静分离

2021.1.21 广西深圳大也科技

map怎么删除

使用迭代器删除在遍历不会出错,使用foreach删除在遍历报错,多线程情况下使用ConcurrentHashMap

笼统的线程问题:比如线程安全,点赞数量怎么解决

点赞如何处理高并发:参考redis 高并发点赞功能的开发消息队列(MQ)及异步操作

实际项目案例:高并发点赞项目案例

消息队列对高并发的处理是将外部的请求调用信息放置在队列中然后后端处理系统按处理能力从消息队列消费消息(相当处理请求),也就是处理一个消费一个这样;这样就保证了后端系统总是在自身处理能力范围内工作。

在不使用消息队列的情况下,用户的请求数据直接写入数据库,在高并发的情况下,会对数据库造成巨大的压力, 同时也使得响应延迟加剧。在使用消息队列后,用户请求的数据发送给消息队列后立即返回,再由消息队列的消费者进程(通常情况下, 该进程通常独立部署在专门的服务器集群上)从消息队列中获取数据, 异步写入数据库。由于消息队列服务器处理速度远快于数据库(消息队列服务器也比数据库具有更好的伸缩性),因此用户的响应延迟可得到有效改善。

2021.1.25 广西蛋卷科技有限公司

MySql几种连接

内连接查询  inner join:两个表的交集

左连接查询 left join:结果集中只出现左表所有记录,右表出现符合条件记录,无法显示的用null填充

右接查询 left join:和上面一样,左右对调而已。

全连接 union:去除重复的数据

全连接 union all:保留重复的数据

mybatis 传多个参数

@Param,封装成对象或map

mybatis xml遍历list

    <insert id="save">
        INSERT INTO user_like(type, type_id, status, user_id,like_time)
        VALUES
        <foreach collection="list" item="item" separator=" , " index="index">
            (#{item.type}, #{item.typeId}, #{item.status}, #{item.userId},#{item.likeTime})
        </foreach>
    </insert>

mysql判断一个月之内的方法或者其他天数之内的

DATE_SUB() 函数从日期减去指定的时间 间隔。

SELECT * FROM tableName WHERE date >= DATE_SUB(CURDATE(),INTERVAL 30 DAY);

springmvc控制器的三种实现方式

  1. 实现Controller接口
  2. 实现HttpRequestHandler 接口
  3. 使用@Controller注解

时间格式化方法

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date now = new Date(); 
String time = sdf.format(now);

自定义排序

java 自定义排序

Spring怎么收集bean的

扫描注解加入容器,类信息都存在beanDefinition,实例化后的单例对象都存在DefaultListableBeanFactory的Map<String, Object> singletonObjects(单例池)

更多的详细只是,无法了解,只能先看个大概,参考下:spring源码系列(三)——beanDefinition 系列文章

Spring 控制反转,依赖注入

IOC:控制反转 Inversion of Control

资源获取方式
    主动
        自己 new Car();
    被动
        资源的获取不是我们自己创建,而是交给一个容器来创建和设置;

DI: 依赖注入

容器能知道哪个组件(类)运行的时候,需要另外一个类(组件) ; 容器通过反射的形式,将容器中准备好的BookService对象注入(利用反射给属性赋值)到BookServlet中;

SpringBoot 优点

  1. 内置容器
  2. 代码,配置文件少了,提高了生产力
  3. 快速整合第三方框架,无需配置文件
  4. 使用java配置,无需xml

2021 2.22 福州佳鼎软件有限公司&福州片刻优学科技有限公司

mq怎么确保消息消费完成

单例模式作用

保证全局只有一个实例

怎么保证HashMap线程安全

使用ConcurrentHashMap

Collections类的synchronizedMap(Map m)方法可以返回一个线程安全的Map

Map map = Collections.synchronizedMap(new HashMap<>());

MySQL索引何时失效

1.有or;
2.复合索引未用左列字段;
3.like以%开头;
4.需要类型转换;
5.where中索引列有运算;
6.where中索引列使用了函数;
7.如果mysql觉得全表扫描更快时(数据少);

高并发写数据解决方案

高并发写入用户信息到数据库

分库分表,缓存(Redis),集群,动静分离,队列

类 String 维护一个字符串池。 当调用 intern 方法时,如果池已经包含一个等于此 String 对象的字符串(该对象由 equals(Object) 方法确定),则返回池中的字符串。可见,当String相同时,String.intern()总是返回同一个对象,因此就实现了对同一用户加锁。由于锁的粒度局限于具体用户,使系统获得了最大程度的并发。

public synchronized void write(Uers u){ 
synchronized(u.getUserId.intern()) { 
// do something 
    } 
}

2021 2.22 福州智信科技有限公司

讲讲面向过程和面向对象

面向过程(C语言)

就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了。

面向对象(c++,java)

是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描述某个事物在整个解决问题的步骤中的行为。

面向对象具有抽象、封装、继承、多态等特性。

封装:是指隐藏对象的属性和实现细节,仅对外提供公共访问方式。

继承:从已有的类中派生出新的类, 新的类能吸收已有类的数据属性和行为,并能扩展新的能力。

多态:一种定义, 多种实现,父类引用指向子类,方法的多态性主要有方法的重载和方法的覆盖。

Redis各个类型应用场景

string:短信验证码,配置信息

hash:一般key为ID或者唯一标示,value对应的就是详情了。如商品详情,个人信息详情,新闻详情等。

list:因为list是有序的,比较适合存储一些有序且数据相对固定的数据。如省市区表、字典表等。因为list是有序的,适合根据写入的时间来排序,如:最新的***,消息队列等。

set:可以简单的理解为ID-List的模式,如微博中一个人有哪些好友,set最牛的地方在于,可以对两个set提供交集、并集、差集操作。例如:查找两个人共同的好友等。

zset:是set的增强版本,增加了一个score参数,自动会根据score的值进行排序。用来做排行榜,我们以当前小时的时间戳作为 zset 的 key,把贴子ID作为 value,点击数评论数等作为 score,当 score 发生变化时更新 score。逆序排序:按分数值递减命令 ZREVRANGEBYSCORE key

索引创建的原则

只对 where 和order by 需要查询的字段设置索引

2022 8.11  长亮科技 驻场银行

用户充值付款因为网络异常,钱扣了,却还没充值上咋办

钱被扣走了,但是订单却未成功!支付掉单异常最全解决方案

主动查单,钱到账了,就给他充,不然就该订单失败,走退款流程

对象创建的方式

  1. new关键字
  2. 反射
  3. Clone方法
  4. 反序列化

spring bean的生命周期

https://www.zhihu.com/question/38597960

实例化对象,设置属性,然后调用一堆前置后置处理器

单体应用与微服务的区别

易于开发和维护:一个微服务只会关注一个特定的业务功能,所以业务清晰,代码量较少。开发和维护单个微服务相对简单。

单个微服务启动较快。

局部修改容易部署:单体应用只要修改,就要重新部署整个应用。对某个微服务进行修改,只需要重新部署这个服务即可。

2022 8.11  天阳科技 驻场银行

Redis的持久化方式

Redis的持久化有两种方式:RDB和AOF,redis默认采用的是RDB的方式。

RDB:记录的是某一时刻的数据,并不是操作,所以,在做数据恢复时,可以直接把 RDB 文件读入内存。

AOF:记录命令的方式

官方的建议是两个同时使用,这样可以提供更可靠的持久化方案。

2022 8.15 力和致远

List 和 set 能存 null

  • List都可以添加null元素
  • HashMap可以有1个key为null的元素,TreeMap不能有key为null的元素
    所以HashSet底层是HashMap,可以有1个null的元素,TreeSet底层是TreeMap,不能有key为null的元素。

Jdk1.8新特性

  • Lambda表达式
  • 函数式接口
  • 方法引用和构造器调用
  • Stream API
  • 接口中的默认方法和静态方法
  • 新时间日期API
  • hashmap结构调整,加了链表
  • Optional

Redis分布式锁理解

七种方案!探讨Redis分布式锁的正确使用姿势

  • 方案一:SETNX + EXPIRE

  • 方案二:SETNX + value值是(系统时间+过期时间)

  • 方案三:使用Lua脚本(包含SETNX + EXPIRE两条指令)

  • 方案四:SET的扩展命令(SET EX PX NX)

  • 方案五:SET EX PX NX  + 校验唯一随机值,再释放锁

  • 方案六: 开源框架~Redisson

  • 方案七:多机实现的分布式锁Redlock

redis缓存雪崩 缓存穿透 缓存击穿

参考:Redis缓存雪崩、缓存穿透、缓存击穿redis之缓存雪崩、缓存穿透、缓存击穿

雪崩:Redis中的缓存数据是有过期时间的,当在同一时间大量的缓存同时失效时就会造成缓存雪崩

穿透:在Redis缓存和数据库中都找不到相关的数据。也就是说这是个非法的查询,客户端发出了大量非法的查询 比如id是负的 ,导致每次这个查询都需要去Redis和数据库中查询。导致MySql直接爆炸!

击穿:缓存击穿和缓存雪崩类似,也是因为Redis中key过期导致的。只不过缓存击穿是某一个热点的key过期导致的。当有一个热点数据突然过期时,就会导致突然有大量的情况直接落到MySql上,导致MySql直接爆炸!

穿透解决办法:

我们首先把MySql中的数据存到布隆过滤器中(由于使用二进制数组,也就是位图所以空间使用很少),之后如果Redis缓存中没有命中,就需要查询MySql数据库前先在布隆过滤器中查询是否在MySql有数据。
在这里插入图片描述

雪崩和击穿,解决办法:

热点数据设置key不过期,用redis分布式锁

既然一瞬间大量请求落到MySql上会导致MySql爆炸!那么就加一点限制,让一时间只有一个相同请求落到MySql上,反正都是查询同一个信息,之后的其他请求就可以去Redis中找了。

2022.10.24 索天科技

Spring注册bean的方式

Spring中注册Bean的方式有哪些?

  1. xml配置

  2. @Component

  3. @Import

  4. FactoryBean

生产者消费者能写出来嘛

看之前线程笔记线程学习笔记(二)


Mysql索引优化

最佳左前缀原则

覆盖索引优化:查找的字段 name 和 age 都包含在联合索引 idx_name_age 的索引树中,这样的查询就是覆盖索引查询
主键索引最好是自增的
防止索引失效:如like 用%开头,对索引列做了计算、函数、类型转换操作,在 WHERE 子句中,如果在 OR 前的条件列是索引列,而在 OR 后的条件列不是索引列,那么索引会失效。


订单表或者其他表怎么设计的

表的数据量小遵循第三范式,表的数据量很大要有适当的冗余,否则多张大表关联查询会爆炸


大数据报表怎么直接导出excel

EasyExcel,如果数据量过大,可以采取分sheet页导出,比如每个sheet导十万导多个sheet页


Shiro原理

由主体subject,安全管理器SecurityManager,领域Realm,认证器Authenticator,授权器Authorizer等组件组成

subject调用安全管理器,安全管理器调用自己实现的认证和授权方法,去认证获取信息,然后返回结果

认证流程:


怎么加密的,具体方法

先摘要(如MD5,sha256),在加密(对称,非对称都行)

大表关联小表查怎么办

先把小表结果返回在用大表in查询

接口设计注意点

  1. 兼容旧版本
  2. 接口安全验证及权限的控制
  3. 接口调用频率的控制
  4. 调用第三方接口,需要考虑调用失败的重试次数,并打印调用失败的日志,方便后续分析问题。
  5. 保证数据冥等性

读写锁

  1. 允许多个线程同时读,但是只允许一个线程写,在线程获取到写锁的时候,其他写操作和读操作都会处于阻塞状态,读锁和写锁也是互斥的,所以在读的时候是不允许写的
  2. ReentrantLock是所有操作都要上锁,所以锁的力度比较大
  3. ReentrantReadWriteLock所有操作上锁的同时可以做到读读操作并发,读写互斥,写写互斥。
  4. 所以两者的区别可以说是在读多写少的情况下一定要使用到ReentrantReadWriteLock,可以提高代码的执行效率。
  5. 特点:读写互斥、写写互斥、读读并发

CompletionService原理

这个用来做异步统计用

CompletionService:可以使得先完成的任务先被取出,减少了不必要的等待时间。ExecutorCompletionService:CompletionService的唯一实现,内部数据结构加了一个

BlockingQueue来保存已经完成的Future对象,没填队列,则使用的是LinkedBlockingQueue队列,只有当这个Future对象状态是结束的时候,才会加入到这个Queue中

具体原理就是ExecutorCompletionService里的私有类QueueingFuture实现了java.util.concurrent.FutureTask#finishCompletion中的done()方法,finishCompletion是完成任务后的操作,QueueingFuture继承了FutureTask并实现了done(),添加任务到阻塞队列中。

    private class QueueingFuture extends FutureTask<Void> {
        QueueingFuture(RunnableFuture<V> task) {
            super(task, null);
            this.task = task;
        }
        protected void done() { completionQueue.add(task); }
        private final Future<V> task;
    }

take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。

2023.2.17 金钱猫

防止订单重复支付

如何防止用户重复提交订单?(上) - 知乎

如何避免订单出现重复支付的问题? - 知乎

老生常谈的问题:电商业务中如何防止重复下单? - 腾讯云开发者社区-腾讯云

生成唯一一个请求ID,后端拿到之后,用请求ID进行redis加锁,获取失败代表重复下单,没有则继续,然后在检查下是否已下单,下了单就返回结果。

这个问题是有购物车这功能,才需要这么做,现在做的这家充值系统不需要

为啥呢?

因为就没有根据订单号来进行下单这接口,前端直接调用预下单接口,就生成一笔支付信息(预下单),返回预下单ID,前端用预下单ID去唤起收银台,才能支付,由于没有待支付列表,所以不会发起重复支付问题,每次请求预下单都会生成一笔新的支付信息对应一笔订单,所以不存在重复支付问题,出了问题也是第三方支付那边再管

订单跨历史表查

先查最新的,再查旧的,最后拼接起来

如何保证数据库和redis一致

只能保证最终一致性,可以使用延时双删,先删缓存,在更新数据库,延时(开个新线程去删,不是在当前线程)一定时间,在删缓存

延迟双删是在先修改数据库再删除缓存的情况下,为了使缓存与数据库达到最终一致,再进行一次延迟删除,称为延迟双删

由于在修改数据库之前,此时缓存可能刚好失效,另一个读取请求进来之后发现缓存中不存在,就会从数据库读取数据,假设此时读取完但还没放到缓存中,这时修改数据库、删除缓存的操作执行先完成,那么读取完放到缓存中的数据就是旧数据,与数据库中的数据不一致

2023.2.18 夸父信息

count * 和count 1 区别

对于count(1),InnoDB引擎会扫描主键索引树,但不取值,server层对于返回的每一行,按行累计加1,判断不可能为NULL,返回累计值。

count(*)可能会扫表

2023.2.22 迅腾科技

数据库自增主键可能的问题

MySQL 插入数据获取 AUTO_INCREMENT 时不会使用事务锁,而是会使用互斥锁,并发的插入事务可能出现部分字段冲突导致插入失败,想要保证主键的连续需要串行地执行插入语句;

2023.2.22 昀宴

慢sql优化经验

量大的sql处理进行分批处理:更新过期卡密的状态为已过期,如直接一次性更新会可能会阻塞住其他sql的执行,优化成分批处理

要命中索引进行查询:有一次千万的大表查询某条记录,由于条件没有使用到索引,且没设置查询范围导致全表扫描,拖垮数据库,后面改用索引条件进行查询

2023.2.23 承启通

ShardingJdbc使用模运算分片,这时候根据模值更改,拓展性不好,比如 ID %10,10变成15,就没办法了

MQ相关问题

先数据库插入,再用mq怎么保证数据库插入失败mq不被消费掉

【项目】数据库事务与MQ发送一致性_mq操作数据库_雨下一整晚real的博客-CSDN博客

实际上在 producer.sendMessage 执行的时候,消息并没有通过网络发送出去,而仅仅是往业务 DB 同一个实例上的消息库插入一条记录,然后注册事务的回调。在这个事务真正提交后消息才从网络发送出去,这个时候如果发送到 consumer 成功的话消息会被立即删除掉。而如果消息发送失败则消息就留在消息库里,这个时候我们会有一个补偿任务会将这些消息从指定的 message db 消息库里捞出然后重新发送,直到发送成功。

乐观锁实现方式,然后会出现的问题

版本号机制

CAS 算法:会出现ABA问题

自己补充的

Spring怎么结局循环依赖

一级缓存:单例池 Map<String, Object> singletonObjects 存放已经经历了完整生命周期的 Bean 对象

二级缓存:存放早期暴露出来的 Bean 对象,Bean 的生命周期未结束(属性还未填充完)Map<String, Object> earlySingletonObjects

三级缓存:存放可以生成 Bean 的工厂 Map<String, ObjectFactory<?>> singletonFactories

Spring通过将实例化后的对象提前暴露给Spring容器中的singletonFactories,解决了循环依赖的问题

参考:Spring 是如何解决循环依赖的?

Mapper 编写有哪几种方式?

  1. 接口实现类继承 SqlSessionDaoSupport
  2. 使用MapperFactoryBean
  3. 使用mapper扫描器

订单超时未支付解决方案

1.扫表轮循
2.懒删除,等用户查询再去更改状态
3.消息延时队列实现
4. Redis过期回调

MQ怎么保证消息顺序性,消息不丢失

如何保证消息的顺序性、消息不丢失、不被重复消费

顺序性

每个 queue 对应一个 consumer(消费者)

不丢失

1.使用消息确认机制,返回ACK

2.持久化

了解java内存模型、GC、线程安全、线程池
了解HashMap数据结构
理解数据库索引原理和innodb特点
Spring重点理解IOC和AOP
笔试算法题推荐冒泡排序、二分查找、二叉树三种遍历
 

CAP、延时双删、redis为什么快、多数据源的底层原理、SpringBoot 启动机制(starter 机制)

类加载

可以在自己的工程中加载自定义的类 (跟jdk自带的类同名)

 maven如何对引入的包进行管理,以 及包冲突的解决 

SpringCloud有哪些模块以及功能

仔细说下注册中心

服务通信的过程中,数据包会通过注 册中心吗

声明式事务Transcation注解失效的情 况 

MySQL中的in和exsit 

Redis的持久化机制 

AOF和RDB哪个的一致性效果会好一 底 

sycronized关键字的原理

synchronized和lock区别 ?

 

从特性来看:
1.synchronized是一个同步关键字,lock是juc包里面提供的一个接口,这个接口他有很多的实现类,其中包括Reentrantlock这个重入锁的实现。

从锁粒度来看:
synchronized可以通过两种方式控制锁的粒度:
1.把synchronized关键字修饰在方法层面
2.修饰在同步代码块上
并且我们可以通过synchronized加锁对象的生命周期,来控制锁的作用范围,比如锁对象是静态对象,或者类对象,那么这个锁就是属于全局锁,如果锁对象是实例对象,那么这个锁的范围取决于这个对象的生命周期。

1.包裹在这两个方法之间的代码能够保证线程安全性。而锁的作用域取决于Lock实例的生命周期。
2.Lock比Synchronized的灵活性更高,Lock可以自主决定什么时候加锁,什么时候释放锁,只需要调用lock()和unlock()这两个方法就行,同时Lock还提供了非阻塞的竞争锁方法tryLock()方法,这个方法通过返回true/false来告诉当前线程是否已经有其他线程正在使用锁。
3.Synchronized由于是关键字,所以它无法实现非阻塞竞争锁的方法,另外Synchronized锁的释放是被动的,就是当Synchronized同步代码块执行完以后或者代码出现异常时才会释放。
5.Lock提供了公平锁和非公平锁的机制,公平锁是指线程竞争锁资源时,如果已经有其他线程正在排队等待锁释放,那么当前竞争锁资源的线程无法插队。而非公平锁,就是不管是否有线程在排队等待锁,它都会尝试去竞争一次锁。 Synchronized只提供了一种非公平锁的实现。

性能方面
synchronized在性能方面和lock相差不大,在实现上会有一个区别synchronized引入了偏向锁,轻量级锁,重量级锁,以及锁升级的机制去实现锁的优化,而lock则用到了自旋锁的方式实现性能优化。

阻塞队列BlockingQueue

ArrayBlockingQueue实现并发同步的原理就是利用ReentrantLock和它的俩个Condition,读操作和写操作都需要先获取到ReentrantLock独占锁才能进行下一步操作。

就是生产者消费者模式写法

  • ArrayBlockingQueue中的锁是没有分离的,即生产和消费用的是同一个锁; 使用一个ReentrantLock来保证线程安全:入列和出列前都需要获取该锁。
  • LinkedBlockingQueue中的锁是分离的,使用两个ReentrantLock来保证线程安全:入列前需要获取到入列锁(putLock),出列前需要获取到出列锁(takeLock),实现了入列锁和出列锁的分离。

非阻塞队列

ConcurrentLickedQueue使用CAS非阻塞算法+不停重试的实际来实现线程安全的。

AQS简单原理

AQS对象内部有一个核心的变量叫做state,是int类型的,代表了加锁的状态;

AQS是一个FIFO的双向队列(多个Node节点,有前后指针),获取不到锁的线程加入到队列中,

线程通过自旋CAS不断去修改state,来获取当前锁

ReentrantLock

ReentrantLock是基于AQS框架实现的锁

ReentrantLock 构造方法默认是不公平的

公平原理:先看下是否有人排队,如果没有排队则尝试获锁;如果有排队,则进入排队队列。

就是当前线程位于队列的头部或队列为空则可以获取锁

非不公平原理:非公平锁的情况下,相对较晚来的线程,在尝试上锁的时候,即使之前已经有等待锁的线程存在,它也是有可能上锁成功的

就是不管当前线程是否在双向队列的头部,都直接尝试获取锁

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
对于面试题文档下载的需求,我可以提供以下答案。 首先,在网上寻找相关的面试题文档下载网站是一种常见的方法。可以通过搜索引擎输入相关关键词,如“面试题文档下载”、“职位面试题集合”等,会有很多网站提供免费或付费的面试题文档下载服务。用户可以根据自己的需求选择合适的网站,浏览并下载自己需要的面试题文档。 另外,与具体面试相关的业或领域网站也会提供相关的面试题文档下载。例如,在招聘网站或业专业网站,可以找到与特定职位或业相关的面试题文档。这些文档通常会包含常见的面试题目和答案,帮助求职者更好地准备面试。 此外,还可以通过与同或朋友交流来获取面试题文档。有时候,一些人可能会有自己精心整理和收集的面试题库,他们乐意与别人分享。可以向他们索取面试题文档,并根据需要进下载和使用。 最后,自己整理和面试题文档也是一个很好的方法。在整个求职和面试过程,我们可能会遇到各种各样的面试题目。可以将这些问题和答案整理成一个个主题,形成自己的面试题文档。随着时间的推移,这个文档会不断完善和积累,成为自己的宝贵资源。 总之,寻找面试题文档下载的方法很多,可以利用网上资源、业专业网站、交流与自身整理等途径。希望以上回答对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值