首页 >> 大全

较劲大厂面试题一---2021年BAT考核趋势JUC-AQS

2023-12-11 大全 24 作者:考证青年

温习读书---------------------------------------------------

开发手册,华山版,泰山版

Java并发编程的艺术

JVM从入门到精通

深入理解JAVA虚拟机

不依赖看帖子、博客和百度和面试题

0、大厂面试复盘

京东一面:AQS源码

阿里一面:syn lock redis新的数据结构 mysql 调优

快手一面:java mysql 循环依赖重点,三级缓存,有没有准备?

58同城: java基础,redis时效性,redis淘汰策略,惰性删除?LRU RDB?热点数据失效怎么处理?击穿 穿透 雪崩?

阿里三面:分布式锁?jmq??jvm?一致性哈希?关键字?cas锁?syn?线程安全?

一、Java 1.1 58同城java字符串常量池《深入理解JAVA虚拟机》

运行结果:

58tongcheng  
58tongcheng  
true  
java  
java  
false  

面试解析:

系统初始化JDK自带的java,不是同一个java。

是加载sun.misc.这个类的时候进入常量池中的。

1.2 字节跳动两数求

1.给定一个数m,求大于该数的最小2的n次密,返回n

2.给定一个数组nums和一个目标值,请你在数组中找出和为目标值的哪两个整数,并返回数组下标

数组暴力破解:

class Solution {public int[] twoSum(int[] nums, int target) {int[] result = new int[2];   //定义返回结果数组for (int i = 0; i < nums.length; i++) {for (int j = 0; j < nums.length; j++) {if (nums[j] == target - nums[i]) { //用target-nums[i]作为查询条件来判断结果if (i != j) {result[0] = j;result[1] = i;break;}}}}return result;  //如果没有返回的是空数组}
}

数据结构解法:

    Map<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 };}map.put(nums[i], i);}throw new IllegalArgumentException("No two sum solution");
}

二、JUC 2.1 可重入锁【递归锁】

在同一个线程在外层方法获取的锁的时候,在即进入该线程的内层方法会自动获取锁,不会阻塞。

都是可重入锁【同步锁】。

: 隐式锁 JVM控制 【自动挡】

: 显示锁Lock ,手动来写 【手动挡】

也是说,同一个线程可以多次获得同一把锁。

也是一样的。

面试大厂ui__2021大厂面试题

2.2 唤醒线程的3种方法

1.中的wait() ()

()放于wait 之前无法执行,无法唤醒,程序一直等待下去。

必须成对,先wait再

2.JUC包中的的 await() ()

限制条件和上面如法炮制。

3.类park() () 可以阻塞当前线程,以及指定被阻塞的线程

单纯的唤醒和阻塞线程,不需要再锁里面。

2.3 【wait/的改良版park/】

用于创建锁和其他基本线程阻塞原语。

每一个线程都有一个许可证, 不是1就是0,可以看成信号量,与其不同的是累加的上限为1.

先等待后唤醒 先唤醒后等待 都是可以的。park()形同虚设。

三、AQS【2021年重点】

抽象的队列同步器 ,构建锁,其他同步器组件及整个JUC体系的基石框架。

FIFO队列来完成排对工作,并通过一个int类型表示锁的持有状态。

ck

与区别于CAS比较并交换,自旋锁。

3.1 锁与同步器的关系?

锁:面向使用者,定义了程序员与锁交互的应统API,隐藏了实现的细节。

同步器:面向所的实现者,java并发大神,提出了一种规范并简化了锁的实现,屏蔽了同步状态的管理,阻塞线程排对和通知,唤醒机制等。

AQS = State变量+CLH变种的双端队列

头尾前后指针全部都有

3.2 读AQS

非公平锁为例,银行办理业务的案例,模拟AQS如何进行现成的管理和通知唤醒机制:

public class Demo01 {public static void main(String[] args) {ReentrantLock lock = new ReentrantLock();/*** 3 个线程模拟银行网点,受理顾客*/// 第一个顾客办理业务,没有人等待,A直接办理20分钟new Thread(()->{lock.lock();try{System.out.println("-----A线程进入-----");// 暂停20分钟TimeUnit.MINUTES.sleep(20);} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}},"A").start();// 第二个顾客办理业务,受理的窗口只有一个,B只能等待new Thread(()->{lock.lock();try{System.out.println("-----B线程进入-----");} finally {lock.unlock();}},"B").start();// 第三个顾客办理业务,受理的窗口只有一个,C只能等待new Thread(()->{lock.lock();try{System.out.println("-----C线程进入-----");} finally {lock.unlock();}},"C").start();}
}

1.A线程首先上锁,需要执行的:

2.BC线程抢不到,修改不了的状态,抢占失败,准备进行排队,执行()方法,模板方法设计模式,抛出异常,

3.B尝试抢占锁,失败,继续尝试()这个方法,准备入队候客区进行补位,

4.新建一个新的节点,并不是当前的节点B,而是一个null,作用就是哨兵节点,进行占位。

此时,就是成了如下的情况:

5.C线程开始准备加入队列,重复B线程的流程,入队执行()方法,抢不到,C与B不同的是,有一个哨兵节点和B节点,

6.B开始进行阻塞,此时才真正的被阻塞,完全入队。

7.A线程办完业务,开始走人,执行()方法

h为头指针,-1不为0,开始进行出队操作。()。

开始进行状态变换,1-1=0,设置当前线程占有为null。释放锁,设置状态=0。

总结:

1.lock方法

2.AQS====调用()---->调用()---->调用()方法

四、

五、Redis

六、JVM

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了