经典面试题

  1. 分布式之数据库和缓存双写一致性方案解析
    1. 先更新DB,再更新CACHE
      1. 线程A更新DB值=1
      2. 线程B更新DB值=2
      3. 线程B更新CACHE值=2
      4. 线程A更新CACHE值=1
      5. 最终缓存中是脏数据1
    2. 先更新CACHE,再更新DB
      1. 线程A淘汰CACHE=0,更新DB=1
      2. 线程B获取CAHCE不存在,更新DB=2
      3. 线程B更新CACHE=2
      4. 线程A更新CACHE=1
      5. 如何解决? — 延迟双删政策
        1. 先淘汰缓存
        2. 在写数据库
        3. 休眠1s,再淘汰缓存
          1. 如果删除缓存再失败?— 异步线程去淘汰:使用MQ或者订阅binlog
  2. 高并发的核心技术-幂等的实现方案
    1. 先查询再检验
    2. 唯一性索引
    3. Mysql insert into ….. on duplicate key update xxx = now()
    4. 悲观锁
    5. 版本号乐观锁
    6. 状态机
  1. 题目:编写一个程序,开启 3 个线程,这三个线程的 ID 分别为 A、B、C,每个线程将自己的 ID 在屏幕上打印 10 遍,要求输出的结果必须按顺序显示。如:ABCABCABC……
  • 使用Lock实现

    1. public static void main(String[] args) {
    2. OrderPrintTestCase1 testCase1 = new OrderPrintTestCase1();
    3. Thread a = new Thread(()-> {testCase1.print(0);},"A");
    4. Thread b = new Thread(()-> {testCase1.print(1);},"B");
    5. Thread c = new Thread(()-> {testCase1.print(2);},"C");
    6. a.start();
    7. b.start();
    8. c.start();
    9. }
    10. private int indexCount = 0;
    11. private int mod = 3;
    12. private int loop = 10;
    13. private static ReentrantLock lock = new ReentrantLock(true);
    14. private void print(int threadIndex) {
    15. for (int i = 0; i < loop; ) {
    16. try {
    17. lock.lock();
    18. if (indexCount % mod == threadIndex) {
    19. System.out.println(Thread.currentThread().getName());
    20. indexCount++;
    21. i++;
    22. }
    23. } finally {
    24. lock.unlock();
    25. }
    26. }
    27. }
  • 使用wait notify实现

    1. public static void main(String[] args) {
    2. OrderPrintTestCase1 testCase1 = new OrderPrintTestCase1();
    3. Thread a = new Thread(()-> {testCase1.print(0);},"A");
    4. Thread b = new Thread(()-> {testCase1.print(1);},"B");
    5. Thread c = new Thread(()-> {testCase1.print(2);},"C");
    6. a.start();
    7. b.start();
    8. c.start();
    9. }
    10. private int indexCount = 0;
    11. private int mod = 3;
    12. private int loop = 10;
    13. private static ReentrantLock lock = new ReentrantLock(true);
    14. private void print(int threadIndex) {
    15. for (int i = 0; i < loop; ) {
    16. try {
    17. lock.lock();
    18. if (indexCount % mod == threadIndex) {
    19. System.out.println(Thread.currentThread().getName());
    20. indexCount++;
    21. i++;
    22. }
    23. } finally {
    24. lock.unlock();
    25. }
    26. }
    27. }

todo: 更好的解法?https://www.yuque.com/huishuohuadeyaba/snpoe3/nasqub

  1. 让3个线程顺序打印数字,如线程1打印1-5,线程2打印6-10,线程3打印11-15,然后是线程1打印16-20…一直打印到75结束。

//此题为上一题衍生,只要每个线程每次占有资源时,打印5次即可。

  1. public static void main(String[] args) {
  2. OrderPrintTestCase1 testCase1 = new OrderPrintTestCase1();
  3. Thread a = new Thread(()-> {testCase1.print(0);},"A");
  4. Thread b = new Thread(()-> {testCase1.print(1);},"B");
  5. Thread c = new Thread(()-> {testCase1.print(2);},"C");
  6. a.start();
  7. b.start();
  8. c.start();
  9. }
  10. private int indexCount = 0;
  11. private int mod = 3;
  12. private int loop = 10;
  13. private static ReentrantLock lock = new ReentrantLock(true);
  14. private void print(int threadIndex) {
  15. for (int i = 0; i < loop; ) {
  16. try {
  17. lock.lock();
  18. if (indexCount % mod == threadIndex) {
  19. System.out.println(Thread.currentThread().getName());
  20. indexCount++;
  21. i++;
  22. }
  23. } finally {
  24. lock.unlock();
  25. }
  26. }
  27. }
  1. 现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?

    1. public static void main(String[] args) {
    2. OrderPrintTestCase1 testCase1 = new OrderPrintTestCase1();
    3. Thread a = new Thread(()-> {testCase1.print(0);},"A");
    4. Thread b = new Thread(()-> {testCase1.print(1);},"B");
    5. Thread c = new Thread(()-> {testCase1.print(2);},"C");
    6. a.start();
    7. b.start();
    8. c.start();
    9. }
    10. private int indexCount = 0;
    11. private int mod = 3;
    12. private int loop = 10;
    13. private static ReentrantLock lock = new ReentrantLock(true);
    14. private void print(int threadIndex) {
    15. for (int i = 0; i < loop; ) {
    16. try {
    17. lock.lock();
    18. if (indexCount % mod == threadIndex) {
    19. System.out.println(Thread.currentThread().getName());
    20. indexCount++;
    21. i++;
    22. }
    23. } finally {
    24. lock.unlock();
    25. }
    26. }
    27. }
  2. 「阿里面试系列」面试加分项,从JVM层面了解线程的启动和停止


7. 如何设计一个秒杀系统
经典面试题 - 图1

  1. 面试必会:Cookie和Session的区别? | 区别 | Cookie | Session | | —- | —- | —- | | 存放位置 | 在Client存放 | 在Server存放 | | 数据类型 | 保存的是String类型 | 保存的是Object类型 | | 生命周期 | 可以长期保存在Client | 数据随会话的结束而结束 | | 数据安全 | 保存不重要的数据 | 保存重要的数据 | | 限制 | 浏览器最多能创建300个;每个最大4kb;一个WEB站点最多存20个Cookie |

    |


作者

URL 备注
https://my.oschina.net/tinyframework/ 恒生架构师罗果
https://mp.weixin.qq.com/s/7F32Ni059ZiDW0YXxk61ng 面试
https://www.cnblogs.com/fangjian0423/p/springMVC-interceptor.html 阿里-SpringMVC技术博客
https://blog.csdn.net/javazejian?t=1 JUC相关
https://blog.csdn.net/quhongwei_zhanqiu 栈秋
https://github.com/doocs/advanced-java 互联网 Java 工程师进阶知识完全扫盲

博客

金三银四跳槽季,Java面试大纲
https://www.toutiao.com/a6658965048179819021/
BAT最全Java面试168题汇总:并发编程+JVM+Spring+分布式+缓存等!
蚂蚁金服的一次面试经历分享!(一面、二面)
回答阿里社招面试如何准备,顺便谈谈对于Java程序猿学习当中各个阶段的建议
Java 集合框架综述