k12机构面试小结

【k12机构面试小结】公司:英语在线培训机构
面试知识点:
1 并发
java线程池常用6大参数以及含义

1 corePoolSize:核心线程数 核心线程会一直存活,及时没有任务需要执行 当线程数小于核心线程数时,即使有线程空闲,线程池也会优先创建新线程处理 设置allowCoreThreadTimeout=true(默认false)时,核心线程会超时关闭 2 queueCapacity:任务队列容量(阻塞队列)用来做缓冲 核心线程数达到最大时,新任务会放在队列中排队等待执行 3 maxPoolSize:最大线程数 当线程数>=corePoolSize,且任务队列已满时。线程池会创建新线程来处理任务 当线程数=maxPoolSize,且任务队列已满时,线程池会拒绝处理任务而抛出异常 4 keepAliveTime:线程空闲时间 当线程空闲时间达到keepAliveTime时,线程会退出,直到线程数量=corePoolSize 如果allowCoreThreadTimeout=true,则会直到线程数量=0 (也就是核心线程长时间没有活干也会退出) 5 allowCoreThreadTimeout:允许核心线程超时 6 rejectedExecutionHandler:任务拒绝处理器 两种情况会拒绝处理任务: 当线程数已经达到maxPoolSize,切队列已满,会拒绝新任务 当线程池被调用shutdown()后,会等待线程池里的任务执行完毕,再shutdown。如果在调用shutdown()和线程池真正shutdown之间提交任务,会拒绝新任务 线程池会调用rejectedExecutionHandler来处理这个任务。如果没有设置默认是AbortPolicy,会抛出异常 ## 任务拒绝处理器处理情形 ThreadPoolExecutor类有几个内部实现类来处理这类情况: AbortPolicy 丢弃任务,抛运行时异常 CallerRunsPolicy 执行任务 DiscardPolicy 忽视,什么都不会发生 DiscardOldestPolicy 从队列中踢出最先进入队列(最后一个执行)的任务 当然也支持自定义处理器

reentrantlock 用法及实现原理
代码示例:

k12机构面试小结
文章图片
image.png
从代码中很容易看出,reentrantlock 相比于sychronized需要在finally中释放锁。如果不在 finally解锁,有可能代码出现异常锁没被释放。
说明: 在jdk1.5里面,ReentrantLock的性能是明显优于synchronized的,但是在jdk1.6里面,synchronized做了优化,他们之间的性能差别已经不明显了
reentrantlock 特点
k12机构面试小结
文章图片
image.png
可中断(这里本身是有死锁的,但是可以通过中断来处理)
package com.protobuf.MultiThreading; import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.lang.management.ThreadMXBean; import java.util.concurrent.locks.ReentrantLock; public class LockInterrupt extends Thread { public static ReentrantLock lock1 = new ReentrantLock(); public static ReentrantLock lock2 = new ReentrantLock(); int lock; public LockInterrupt(int lock, String name) { super(name); this.lock = lock; } @Override public void run() { try { if (lock == 1) { lock1.lockInterruptibly(); try { Thread.sleep(500); } catch (Exception e) { // TODO: handle exception } lock2.lockInterruptibly(); } else { lock2.lockInterruptibly(); try { Thread.sleep(500); } catch (Exception e) { // TODO: handle exception } lock1.lockInterruptibly(); } } catch (Exception e) { // TODO: handle exception } finally { if (lock1.isHeldByCurrentThread()) { lock1.unlock(); } if (lock2.isHeldByCurrentThread()) { lock2.unlock(); } System.out.println(Thread.currentThread().getId() + ":线程退出"); } } public static void main(String[] args) throws InterruptedException { LockInterrupt t1 = new LockInterrupt(1, "LockInterrupt1"); LockInterrupt t2 = new LockInterrupt(2, "LockInterrupt2"); t1.start(); t2.start(); Thread.sleep(1000); //DeadlockChecker.check(); System.out.println("ok"); } static class DeadlockChecker { private final static ThreadMXBean mbean = ManagementFactory .getThreadMXBean(); public static void check() { Thread tt = new Thread(() -> { { // TODO Auto-generated method stub while (true) { long[] deadlockedThreadIds = mbean.findDeadlockedThreads(); if (deadlockedThreadIds != null) { ThreadInfo[] threadInfos = mbean.getThreadInfo(deadlockedThreadIds); for (Thread t : Thread.getAllStackTraces().keySet()) { for (int i = 0; i < threadInfos.length; i++) { if (t.getId() == threadInfos[i].getThreadId()) { System.out.println(t.getName()); t.interrupt(); } } } } try { Thread.sleep(5000); } catch (Exception e) { // TODO: handle exception } }} }); tt.setDaemon(true); tt.start(); } } }

死锁具体情形如下,但是上文的守护线程可以通过中断的方式解决死锁。但是对于sychronized 如果获取不到锁只能阻塞等待,因此没有这个机制
k12机构面试小结
文章图片
可限时
超时不能获得锁,就返回false,不会永久等待构成死锁
使用lock.tryLock(long timeout, TimeUnit unit)来实现可限时锁,参数为时间和单位。
公平锁
一般意义上的锁是不公平的,不一定先来的线程能先得到锁,后来的线程就后得到锁。不公平的锁可能会产生饥饿现象。
公平锁的意思就是,这个锁能保证线程是先来的先得到锁。虽然公平锁不会产生饥饿现象,但是公平锁的性能会比非公平锁差很多。
## 使用方法 public ReentrantLock(boolean fair) public static ReentrantLock fairLock = new ReentrantLock(true);

ConcurrentHashmap实现原理以及使用方法(重新写一篇详细介绍)
redis分布式实现原理(重新写一篇详细介绍)
docker知识点(重新写一篇详细介绍)
redis 并发数据结构以及pipline
常用linux命令
java的复制clone() 命令(重新写一篇节详细介绍)
2 接口编程
restful API的好处,如何实现资源间的耦合
## 之前在老部门做过reseful的接口,可惜忘记的差不多了。 REST是什么?(Resource Representational State Transfer: 资源代表状态变化) Resource:资源,即数据(前面说过网络的核心) Representational:某种表现形式: 比如用JSON,XML,JPEG等 State Transfer:状态变化。通过HTTP动词实现 简单介绍: restful API中,url中只使用名词来指定资源, 原则上不使用动词。“资源”是REST架构或者整个网路处理的核心。## pf: http://api.qc.com/v1/newsfeed: 获取某人的信息; http://api.qc.com/v1/friends: 获取某人的好友列表; http://api.qc.com/v1/profile: 获取某人的详细信息但是只有资源,没有操作方法,并不知道具体要做些什么?那么这个时候就需要动词来实现GET 用来获取资源 POST用来新建资源(也可以用于更新资源 pf:http://api.qc.com/v1/friends PUT 用来更新资源 (PUT http://api.qc.com/v1/profile: 更新个人资料) DELETE用来删除资源。(比如:DELETE http://api.qc.com/v1/friends, 删除某人的好友, 在http parameter指定好友id)优势: 接口制定简单,通过url就知道要做什么 看Url就知道要什么 看http method就知道干什么 看http statuscode就知道结果如何

spring mvc 具体实现以及过程,分发器,hander等
参考[6]
3 工具类知识点
kafka具体了解哪些知识点
zookeeper 具体了解哪些知识点
4 提高篇
你认为上一段工作自己做的比较好的地方
经常通过哪些渠道学习,举例自己学习到的知识点
5 mysql:
question: 写出同时用username + age做 联合主键的查询语句 ?
注意此时是将a,b,c三列所有不同的组合全部列出来,而不仅仅只是distinct a 方案一: distinct多列 select distinct a,b,c from tableA; 方案二:group by select a,b,c from tableA group by a,b,c

mysql的7大事务传播机制
PROPAGATION_REQUIRED支持当前事务,如果当前没有事务,则新建一个事(spring 默认) PROPAGATION_SUPPORTS 支持,如果当前没有则以非事务方式执行 PROPAGATION_MANDATORY 支持,如果没有强制抛出异常 PROPAGATION_REQUIRES_NEW 新建,如果存在挂起当前事务 PROPAGATION_NOT_SUPPORTED 以非事务方式运行,如果存在事务则挂起事务 PROPAGATION_NEVER —— 以非事务方式执行,如果当前存在事务,则抛出异常 PROPAGATION_NESTED —— Nested的事务和它的父事务是相依的,它的提交是要等和它的父事务一块提交的。 小结: 其实可以看出事务的是从支持事务和不支持事务的顺序过渡

Spring事务的5种隔离级别
1、ISOLATION_DEFAULT (使用DB默认隔离级别) 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别。另外4个与 JDBC 的隔离级别相对应。2、ISOLATION_READ_UNCOMMITTED(对应mysql:UNCOMMITTED )这是事务最低的隔离级别,它允许另外一个事务可以看到这个事务未提交的数据。 这种隔离级别会产生脏读,不可重复读和幻读。3、 ISOLATION_READ_COMMITTED(对应mysql:READ_COMMITTED)保证一个事务修改的数据提交后才能被另外一个事务读取,其它事务不能读取该事务未提交的数据。4、ISOLATION_REPEATABLE_READ(对应mysql:REPEATABLE_READ) mysql 默认隔离级别保证一个事务不能读取另一个事务未提交的数据,避免了“脏读取”和“不可重复读取”的情况,但是带来了更多的性能损失。这种事务隔离级别可以防止脏读,不可重复读,但是可能出现幻读。5、ISOLATION_SERIALIZABLE(对应mysql:SERIALIZABLE)这是最可靠的但是代价花费最高的事务隔离级别,事务被处理为顺序执行。 除了可防止脏读,不可重复读外,还避免了幻读

具体实例详解参考3
6 vim 常用命令,大文件替换文本等
## 对第一行到最后一行的内容进行替换(即全部文本)多种写法 :1,$s/from/to/g :%s/from/to/g

参考文献:
1 distinct 多列详解
2 Spring 七种事务传播机制和五种事务隔离级别
3 脏读、幻读和不可重复读 + 事务隔离级别
4 Vim文本替换
5 RESTful API
6 SpringMVC执行流程及工作原理
7 reentrantlock可重入锁

    推荐阅读