L学姐京东后端一面面经

京东0310

1.自我介绍

2.介绍项目难点

根据个人,视情况而定

3.Integer a = new Integer(10); Integer b = new Interger(10) a==b?

class test1 {
    public static void main(String[] args) {
        Integer integer1 = new Integer(10);
        Integer integer2 = new Integer(10);
        System.out.println(integer1 == integer2);
        System.out.println(integer1.equals(integer2));


        Integer integer3 = new Integer(100);
        Integer integer4 = new Integer(100);
        System.out.println(integer3 == integer4);
        System.out.println(integer3.equals(integer4));
    }
}

在这里插入图片描述

==:为false

equals:为true

4.Integer a = 100,Integer b = 100 a == b ? Integer a= 255;Integer b = 255 a==b?

class test {
    public static void main(String[] args) {
        Integer integer1 = 100;
        Integer integer2 = 100;
        System.out.println(integer1 == integer2);

        Integer integer3 = 255;
        Integer integer4 = 255;
        System.out.println(integer3 == integer4);
    }
}

在这里插入图片描述
true;false

5.HashMap 1.7/1.8 优化,是否为线程安全的;

HashMap的线程不安全主要是体现在下面两个方面:

① 在JDK1.7 中,当并发执行扩容操作时会造成 环形链 和 数据丢失 的情况;

② 在JDK1.8 中,在并发执行put操作的过程中,会出现 数据覆盖 的情况。

6.安全的线程HashMap,为什么?

HashTable:采用synchronized方法上加锁,使用阻塞同步,效率低。

collections.synchronizedMap(map):也是采用synchronized方法上加锁,使用阻塞同步,效率低。

ConcurrentHashMap:采用锁分段技术,减小锁的粒度,效率高

7.说一下ConcurrentHashMap

ConcurrentHashMap中是一次锁住一个桶。

ConcurrentHashMap默认将hash表分为16个桶,诸如get,put,remove等常用操作只锁当前需要用到的桶。

这样,原来只能一个线程进入,现在却能同时有16个写线程执行,并发性能的提升是显而易见的。上面说到的16个线程指的是写线程,而读操作大部分时候都不需要用到锁。只有在size等操作时才需要锁住整个hash表。

8.线程池和普通线程的区别?好处是什么?

一:线程和线程池的区别

(1)new Thread 的弊端

  • 每次new Thread时,新建对象性能差。
  • 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,可能占用过多系统资源导致死机或oom。
  • 缺乏更多功能,如定时执行、定期执行、线程中断。

(2)Java提供的四种线程池相比new Thread的优势

  • 重用存在的线程,减少对象创建、消亡的开销,性能佳。
  • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。
  • 提供定时执行、定期执行、单线程、并发数控制等功能。

Java通过Executors提供四种线程池

newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。
newFixedThreadPool 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
newScheduledThreadPool 创建一个定长线程池,支持定时及周期性任务执行。
newSingleThreadExecutor 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级执行。

9.线程池的几个参数?拒绝策略(4个)? 模拟向线程池中添加一个线程的步骤;

一、corePoolSize 线程池核心线程大小

二、maximumPoolSize 线程池最大线程数量

三、keepAliveTime 空闲线程存活时间

四、unit 空闲线程存活时间单位

五、workQueue 工作队列

六、threadFactory 线程工厂

七、handler 拒绝策略

10.线程池核心线程数的设置,并发量小但是时间不长应该怎么设置呢? 并发量大但是时间短怎么设置(和CPU个数有关)

一般说来,大家认为线程池的大小经验值应该这样设置:(其中N为CPU processors的个数)
(1)如果是CPU密集型应用,则线程池大小设置为N+1(或者是N),线程的应用场景:主要是复杂算法。
(2)如果是IO密集型应用,则线程池大小设置为2N+1(或者是2N),线程的应用场景:主要是:数据库数据的交互,文件上传下载,网络数据传输等等。
+1的原因是:即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时,这个额外的线程也能确保CPU的时钟周期不会被浪费。

11.提交线程的方法,(2个) 有什么区别?

线程池提交方式有两种:execute()和submit()

两种方式提交的区别:

(1)execute只能提交Runnable类型的任务,无返回值。submit既可以提交Runnable类型的任务,也可以提交Callable类型的任务,会有一个类型为Future的返回值,但当任务类型为Runnable时,返回值为null。
(2)execute在执行任务时,如果遇到异常会直接抛出,而submit不会直接抛出,只有在使用Future的get方法获取返回值时,才会抛出异常。

12.退出线程池的方法;

线程池 API 提供两个主动关闭的方法 ThreadPoolExecutor#shutdownNowThreadPoolExecutor#shutdown,这两个方法都可以用于关闭线程池,但是具体效果却不太一样。

13.讲一下JVM,有关JVM的一切 说了内存区域,每个内存区域是干什么的,垃圾回收器的不同;垃圾回收算法,堆的分类

14.数据库索引的结构,为什么(说了Hash表和B+数的区别)?

Hash索引和B+树索引的底层实现原理:

hash索引底层就是hash表,进行查询时,调用一次hash函数就可以获取到相应的键值,之后进行回表查询获得实际数据.

B+树底层实现原理是多路平衡查找树,对于每一次的查询都是从根节点出发,查询到叶子节点方可以获得所查键值,然后查询判断是否需要回表查询.

区别:

hash索引

1:hash索引进行等值查询更快(一般情况下)但是却无法进行范围查询.因为在hash索引中经过hash函数建立索引之后,索引的顺序与原顺序无法保持一致,不能支持范围查询.

2:hash索引不支持模糊查询以及多列索引的最左前缀匹配,因为hash函数的不可预测,eg:AAAA和AAAAB的索引没有相关性.

3:hash索引任何时候都避免不了回表查询数据.

4:hash索引虽然在等值上查询叫快,但是不稳定,性能不可预测,当某个键值存在大量重复的时候,发生hash碰撞,此时查询效率可能极差.

5:hash索引不支持使用索引进行排序,因为hash函数的不可预测.

B+树

1:B+树的所有节点皆遵循(左节点小于父节点,右节点大于父节点,多叉树也类似)自然支持范围查询.

2:在符合某些条件(聚簇索引,覆盖索引等)的时候可以只通过索引完成查询.不需要回表查询.

3:查询效率比较稳定,对于查询都是从根节点到叶子节点,且树的高度较低.

结论:

大多数情况下,直接选择B+树索引可以获得稳定且较好的查询速度,而不需要使用Hash索引.

15.聚簇索引和非聚簇索引的区别?

都是B+树的数据结构

  • 聚簇索引:将数据存储和索引放在一起、并且是按照一定的顺序组织的,找到索引也就找到了数据,数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻的存放在磁盘上的。
  • 非聚簇索引:叶子节点不存储数据,存储的是数据行地址,也就是说根据索引查找到数据行的位置再去磁盘查找数据,这就有点类似一本书的目录,比如要找到第三章第一节,那就现在目录里面查找,找到对应的页码后再去对应的页码看文章。

16.最左匹配 where a = 1 and b > 10 and c= 10 索引怎么走?

17.Spring事务了解过吗?

事务传播机制:事务的特性

事务的隔离级别:脏读、幻读、不可重复读

只读

事务超时

回滚规则

18.MyBatis用过吗? MyBatis的#和$区别?

1 #是将传入的值当做字符串的形式,eg:select id,name,age from student where id =#{id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id =‘1’

2 是 将 传 入 的 数 据 直 接 显 示 生 成 s q l 语 句 , e g : s e l e c t i d , n a m e , a g e f r o m s t u d e n t w h e r e i d = 是将传入的数据直接显示生成sql语句,eg:select id,name,age from student where id = sqleg:selectid,name,agefromstudentwhereid={id},当前端把id值1,传入到后台的时候,就相当于 select id,name,age from student where id = 1

3 使用#可以很大程度上防止sql注入。(语句的拼接)

4 但是如果使用在order by 中就需要使用 $

5 在大多数情况下还是经常使用#,但在不同情况下必须使用$.

我觉得#与的区别最大在于:#{} 传入值时,sql解析时,参数是带引号的,而{}传入值,sql解析时,参数是不带引号的。

19.MyBatis的接口是怎么和XML文件联系上的?

mybatis 会先解析这些xml 文件,通过 xml 文件里面的命名空间 (namespace)跟dao 建立关系;然后 xml 中的每段 sql 会有一个id 跟 dao 中的接口进行关联。

当我们执行MyBatis方法的时候 就通过 全限定类名+方法名 找到MapperedStatement 对象,然后执行里面的sql内容,执行即可

20.快排!

class Solution {
    public int[] sortArray(int[] nums) {
        quickSort(nums, 0, nums.length - 1);
        return nums;
    }
    public void quickSort(int[] arr, int start, int end) {
        int left = start, right = end;
        if(left < right) {
            int temp = arr[left];
            while(left < right) {
                while(left < right && arr[right] > temp) {
                    right--;
                }
                if(left < right) {
                    arr[left] = arr[right];
                }
                while(left < right && arr[left] < temp) {
                    left++;
                }
                if(left < right) {
                    arr[right] = arr[left];
                }
            }
            arr[left] = temp;
            quickSort(arr, start, left);
            quickSort(arr, left + 1, end);
        }
    }
}

21.两数之和!

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer, Integer> map = new HashMap<>();
        for(int i = 0; i < nums.length; i++) {
            int complement = target - nums[i];
            if(map.containsKey(complement)) {
                return new int[] {map.get(complement), i};
            } else {
                map.put(nums[i], i);
            }
        }
        return null;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值