京东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#shutdownNow
与 ThreadPoolExecutor#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 = 是将传入的数据直接显示生成sql语句,eg: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;
}
}