记录草稿:比较仓促 随便一写
------------- 自我介绍 ------------- 面试java开发岗位 项目经验 银行信用卡业务 互联网渠道 微信小程序 支付宝 adp银行信用卡业务 k8s docker springclould rabbitmq kafuka 网络 nginx 节点 前后分离 到达网关 网关走k8s 节点 硬件负载 软件:容器概念 扩充实例节点 ------------- 问题 ------------- 高并发问题:节点--> 压测预估 限流、扩容 熔断 拦截后 请求怎么返回 --> 重试机制 springcould 组件:gateway eureka 熔断器 配置中心(轻舟,阿波罗) Nacos(阿里) 区别:集成了配置中心 分布式事务:单独处理 接口密传 redis锁 :分布式事务怎么设计的:秒杀--》单位时间内锁轮询 共享变量 队列、限流、扩容 分布式事务 cap 多线程场景:线程池 springboot 注解 配置参数 线程池的操作细节和流程 容我想一下这个流程 全局锁? synchronized升级 串行化 指令级 升级后 锁什么?标志位 对象 悲观锁 乐观锁 有哪些 怎么用的 cas 弊端?多线程情况,aba 解决 java 原子类执行 数据库:oracle mysql 引擎innerdb 索引 类型 聚集索引、、非聚集索引 怎么判断有没有索引 explain like不会用到索引 最左原则 设计模式:工厂 单例 策略 装饰器 0代理模式:反射 解决了什么问题 事务,日志 动态代理jdk,cglib java对象克隆 深拷贝浅拷贝 java 多态 构造方法 常用的集合 队列特点 java jdk 11 更新了什么 你还有什么问题吗 技术栈 业务方面 技术 收索引擎 平台是主要做什么 --------------- 评价 --------------- 技术掌握比较全面 数据库相关了解较少 对Java基础了解较少
解析问题:
第一个问题由高并发入手:
Question 1 :如何理解java高并发,如何解决,什么方式解决
面试者回答:前期压测 后期限流
网上高阶答案:大佬解决方式
解读高阶思想
加缓存 导致超发问题加悲观锁 影响效率消息队列 FIFO队列思路 队列瞬间被撑爆加乐观锁 增大CPU的计算开销 相对较好缓存服务器
互联网正在高速发展,使用互联网服务的用户越多,高并发的场景也变得越来越多。电商秒杀和抢购,是两个比较典型的互联网高并发场景。虽然我们解决问题的具体技术方案可能千差万别,但是遇到的挑战却是相似的,因此解决问题的思路也异曲同工。
个人整理并发解决方案。
a.应用层面:读写分离、缓存、队列、集群、令牌、系统拆分、隔离、系统升级(可水平扩容方向)。
b.时间换空间:降低单次请求时间,这样在单位时间内系统并发就会提升。
c.空间换时间:拉长整体处理业务时间,换取后台系统容量空间。
Question 2 : springcould 组件
1 eureka 和 nacos的区别
区别
2 Hystrix(熔断器)
Question 3 : 分布式事务
CAP:一致性(Consistency)、可用性(Availability)、分区容错性(Partition tolerance)
cp ap
Question 4 : 多线程
线程池
handler的拒绝策略:
有四种:
第一种AbortPolicy:不执行新任务,直接抛出异常,提示线程池已满
第二种DisCardPolicy:不执行新任务,也不抛出异常
第三种DisCardOldSetPolicy:将消息队列中的第一个任务替换为当前新进来的任务执行
第四种CallerRunsPolicy:直接调用execute来执行当前任务
五,四种常见的线程池:
CachedThreadPool:可缓存的线程池,该线程池中没有核心线程,非核心线程的数量为Integer.max_value,就是无限大,当有需要时创建线程来执行任务,没有需要时回收线程,适用于耗时少,任务量大的情况。
SecudleThreadPool:周期性执行任务的线程池,按照某种特定的计划执行线程中的任务,有核心线程,但也有非核心线程,非核心线程的大小也为无限大。适用于执行周期性的任务。
SingleThreadPool:只有一条线程来执行任务,适用于有顺序的任务的应用场景。
FixedThreadPool:定长的线程池,有核心线程,核心线程的即为最大的线程数量,没有非核心线程
Question 6 : jdk新特性
引自
- jdk8
Lambda表达式
//使用java匿名内部类 Comparatorcpt = new Comparator () { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1,o2); } }; TreeSet set = new TreeSet<>(cpt); System.out.println("========================="); //使用JDK8 lambda表达式 Comparator cpt2 = (x,y) -> Integer.compare(x,y); TreeSet set2 = new TreeSet<>(cpt2);
// java7中 筛选产品为nike的 public ListfilterProductByColor(List list){ List prods = new ArrayList<>(); for (Product product : list){ if ("nike".equals(product.getName())){ prods.add(product); } } return prods; } // 使用 lambda public List filterProductByPrice(List list){ return list.stream().filter(p->"nike".equals(p.getName())).collect(Collectors.toList()); }
函数式接口
public static void main(String[] args) {
List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
// Predicate predicate = n -> true
// n 是一个参数传递到 Predicate 接口的 test 方法
// n 如果存在则 test 方法返回 true
System.out.println("输出所有数据:");
// 传递参数 n
eval(list, n->true);
// Predicate predicate1 = n -> n%2 == 0
// n 是一个参数传递到 Predicate 接口的 test 方法
// 如果 n%2 为 0 test 方法返回 true
System.out.println("输出所有偶数:");
eval(list, n-> n%2 == 0 );
// Predicate predicate2 = n -> n > 3
// n 是一个参数传递到 Predicate 接口的 test 方法
// 如果 n 大于 3 test 方法返回 true
System.out.println("输出大于 3 的所有数字:");
eval(list, n-> n > 3 );
}
public static void eval(List list, Predicate predicate) {
for(Integer n: list) {
if(predicate.test(n)) {
System.out.println(n + " ");
}
}
}
Predicate
接收一个值返回boolean
Predicate p = t->true;
Supplier
无接受参数返回一个值
Suppliers = () -> new T();
Consumer
接受一个参数无返回值
Consumerc = c -> System.out.println(s);
Function
接受参数T 返回参数R
Functionf = c -> String.valueof(c);
方法引用
静态引用:
格式:Class::static_method
Listlist = Arrays.asList("a","b","c"); list.forEach(str -> System.out.print(str)); list.forEach(System.out::print);
构造器调用
构造器方法引用格式:Class::new,调用默认构造器
Listlist = Arrays.asList("a","b","c"); List list.stream().map(Test::new).collect(Collectors.toList()); public class Test{ private final String desc; public Test(String desc){ this.desc=desc; } }
方法调用
格式:instance::method
Listlist = Arrays.asList("a","b","c"); Test test = new Test(); List list.stream().map(test::toAdd).collect(Collectors.toList()); public class Test{ private final String desc; public Test(String desc){ this.desc=desc; } public String toAdd(String desc){ return desc+"add"; } }
Stream API
// 使用jdk1.8中的Stream API进行集合的操作
@Test
public void test(){
// 循环过滤元素
proList.stream()
.fliter((p) -> "红色".equals(p.getColor()))
.forEach(System.out::println);
// map处理元素然后再循环遍历
proList.stream()
.map(Product::getName)
.forEach(System.out::println);
// map处理元素转换成一个List
proList.stream()
.map(Product::getName)
.collect(Collectors.toList());
}
接口中的默认方法和静态方法
public interface ProtocolAdaptor {
ProtocolAdaptor INSTANCE = DynamicLoader.findFirst(ProtocolAdaptor.class).orElse(null);
default ProtocolAdaptor proxy() {
return (ProtocolAdaptor) Proxy.newProxyInstance(ProtocolAdaptor.class.getClassLoader(),
new Class[]{ProtocolAdaptor.class},
(proxy, method, args) -> intercept(method, args));
}
}
- Optional
用于处理对象空指针异常
public String getDesc(Test test){
return Optional.ofNullable(test)
.map(Test::getDesc).else("");
}
- JDK 11
从Java 10开始,您可以声明没有其类型的局部变量。您只需要定义var关键字而不是类型。从Java 11开始,您还可以将其与lambda表达式一起使用,如下所示
public String sumOfString() {
BiFunction func = (var x, var y) -> x + y;
return func.apply("abc", "efg");
}



