├── .idea ├── Java面试宝典.iml ├── encodings.xml ├── inspectionProfiles │ └── Project_Default.xml ├── misc.xml ├── modules.xml └── vcs.xml ├── Dubbo └── Apache Dubbo.md ├── ElasticSearch └── ES.md ├── Git └── Git.md ├── JVM ├── JVM.md └── assets │ ├── 1547211103015.png │ ├── 1547213596316.png │ ├── 1547217765018.png │ ├── 1547218853370.png │ ├── 1547220419682.png │ ├── 1547466178656.png │ ├── 1547467164358.png │ ├── 1547468174933.png │ ├── 1547563769397.png │ ├── 1550822725879.png │ ├── 1550825623867.png │ ├── 1550825641737.png │ ├── 1550835491284.png │ ├── 1551143665881.png │ ├── 1551143686368.png │ ├── 1551143711681.png │ ├── 1551144443784.png │ ├── 1551146799869.png │ ├── 1551146848389.png │ ├── wpsEB12.tmp.jpg │ ├── wpsF2F8.tmp.jpg │ └── wpsF87B.tmp.jpg ├── Java基础 ├── Java8新特性.md ├── Java9新特性.md ├── Java基础.md ├── Java网络编程.md └── assets │ ├── 1550994028985.png │ ├── 1550994192470.png │ ├── 1550994395358.png │ ├── 1551191608732.png │ ├── 1551592963527.png │ └── 1561973717974.png ├── Java集合类 ├── Java集合——ArrayList.md ├── Java集合——HashMap.md ├── Java集合——HashSet.md ├── Java集合——Hashtable.md ├── Java集合——LinkedHashMap.md ├── Java集合——LinkedList.md ├── Java集合——Stack.md ├── Java集合——TreeMap.md ├── Java集合——TreeSet.md ├── Java集合——Vector.md └── assets │ ├── 1545373231486.png │ ├── 1545373273549.png │ ├── 1545382028006.png │ ├── 1545382296775.png │ ├── 1545382402926.png │ ├── 1545382500758.png │ ├── 1545382564275.png │ ├── 1545382588262.png │ ├── 1545382622346.png │ ├── 1545383369548.png │ ├── 1545388481935.png │ ├── 1545388594643.png │ ├── 1545388638099.png │ ├── 1545388667403.png │ ├── 1545388729610.png │ ├── 1545389017751.png │ ├── 1545389307255.png │ ├── 1545389320129.png │ ├── 1545389576804.png │ ├── 1545389772766.png │ ├── 1545389853050.png │ ├── 1545391584232.png │ ├── 1545391830662.png │ ├── 1545392082121.png │ ├── 1545392093353.png │ ├── 1545392334936.png │ ├── 1545392354319.png │ ├── 1545392442561.png │ ├── 1545392460658.png │ ├── 1545392933952.png │ ├── 1545401798571.png │ ├── 1545402146851.png │ ├── 1545402318913.png │ ├── 1545402552154.png │ ├── 1545402644510.png │ ├── 1545402676747.png │ ├── 1545403220901.png │ ├── 1545403286365.png │ ├── 1545547808198.png │ ├── 1545548231371.png │ ├── 1545549283999.png │ ├── 1545549518834.png │ ├── 1545551281396.png │ ├── 1545553423888.png │ ├── 1545556394817.png │ ├── 1545557010001.png │ ├── 1545828744891.png │ ├── 1545901568538.png │ ├── 1550627367494.png │ ├── 1550628222261.png │ ├── 1550628241555.png │ ├── 1551188876539.png │ ├── 1551189103471.png │ ├── 1551189233419.png │ ├── 1551189400227.png │ ├── 1551189416163.png │ ├── 1558524788238.png │ ├── 1558525322177.png │ └── 1558529309195.png ├── Kubernetes ├── Kubernetes.md ├── assets │ ├── 1593172424925.png │ ├── 1593173010870.png │ ├── 1593174370946.png │ ├── 1593174473066.png │ └── 1593174566864.png └── 资料 │ ├── mytomcat-rc.yaml │ └── mytomcat-svc.yaml ├── Linux ├── Linux.md └── Linux2.md ├── Maven ├── Maven.md └── assets │ ├── 1562154899070.png │ ├── 1562155173376.png │ ├── 1562155253276.png │ └── 1562155455144.png ├── Mysql ├── Mysql七种join.md ├── assets │ ├── 1550386270485.png │ ├── 1550399006096.png │ ├── 1550400143482.png │ ├── 1550467448201.png │ ├── 1550468251532.png │ ├── 1550468294210.png │ ├── 1550728150375.png │ ├── 1550728228269.png │ ├── 1550728239905.png │ ├── 1550728619714.png │ ├── 1550728646391.png │ ├── 1550728862668.png │ ├── 1550728956375.png │ ├── 1550729396796.png │ ├── 1550729590333.png │ ├── 1550729615581.png │ ├── 1550730034562.png │ ├── 1566890429079.png │ └── 1567417612154.png ├── mysql.md ├── 数据库基本理论.md ├── 数据库实战.md └── 订单系统分库分表.md ├── Nginx └── Nginx.md ├── ORM ├── Mybatis原理.md ├── assets │ ├── 1550934048277.png │ ├── 1550934127858.png │ ├── 1550976038601.png │ ├── 1551851951248.png │ ├── 1551851960403.png │ ├── 1551852796288.png │ └── 1551852827882.png └── 数据库连接池.md ├── README.md ├── RabbitMQ ├── assets │ └── 1562315466839.png └── 消息队列.md ├── Redis └── Redis.md ├── Spring Cloud Alibaba ├── Spring Cloud Alibaba.md └── assets │ ├── 1566555914717.png │ ├── 1566556778593.png │ └── 1566558467634.png ├── Spring ├── Java反射机制.md ├── Spring.md ├── SpringAOP.md ├── SpringIOC.md ├── Spring中的设计模式.md ├── Spring事务管理.md ├── Spring面试题.md ├── assets │ ├── 1550488358174.png │ ├── 1550488375749.png │ ├── 1550581880971.png │ ├── 1550581966935.png │ ├── 1550733141548.png │ ├── 1550733552430.png │ ├── 1550734532649.png │ ├── 1550734606220.png │ ├── 1550735364108.png │ ├── 1550738778890.png │ ├── 1550994028985.png │ ├── 1550994192470.png │ ├── 1550994395358.png │ ├── 1551191608732.png │ ├── 1551592963527.png │ ├── 1557750040106.png │ ├── 1557750800454.png │ ├── 1564648587419.png │ ├── 1564650051415.png │ └── 1564650152116.png └── 代理设计模式.md ├── SpringBoot ├── SpringBoot原理.md ├── assets │ ├── 1556789923645.png │ ├── 1556790038353.png │ ├── 1556796082989.png │ ├── 1556804669001.png │ ├── 1556806242329.png │ ├── 1556806882017.png │ ├── 1556807205726.png │ ├── 1556809179729.png │ ├── 1556809213048.png │ ├── 1556809282699.png │ ├── 1556809408300.png │ ├── 1556809827948.png │ ├── 1556809947047.png │ ├── 1556810239953.png │ ├── 1556810363718.png │ ├── 1556810437699.png │ ├── 1557136223672.png │ ├── 1557145511355.png │ └── 1557149435665.png └── 手写SpringBoot.md ├── SpringCloud └── SpringCloud.md ├── SpringMVC ├── SpringMVC.md └── assets │ ├── 1550848187317.png │ ├── 1550848309783.png │ ├── 1550917918683.png │ └── 1550917982183.png ├── java基础 (1).xmind ├── 分布式 ├── RPC.md ├── 一致性哈希.md ├── 分布式.md ├── 分布式锁.md └── 微服务调用.md ├── 刷题 ├── LeetCode.md ├── LeetCode精.md ├── Programmer Code Interview Guide.md ├── Top Interview Questions.md ├── assets │ └── 1561196630964.png ├── leetcode-markdown │ ├── HashMap.md │ ├── 二分查找.md │ └── 树.md ├── 剑指Offer.md └── 动态规划 │ ├── (120)三角形最小路径和.md │ ├── (221)最大正方形.md │ ├── (84)柱状图中最大的矩形.md │ └── (85)最大矩形.md ├── 前端 └── 前端.md ├── 原理 ├── JDBC.md ├── assets │ ├── 1555075439248.png │ └── 1555076016953.png └── 学习大纲.jpg ├── 响应式编程 └── 响应式编程.md ├── 场景题 ├── 场景题.md └── 海量数据查询.md ├── 大纲.md ├── 并发编程 ├── ForkJoin框架.md ├── JUC锁.md ├── JUC集合 │ ├── JUC集合——ArrayBlockingQueue.md │ ├── JUC集合——ConcurrentHashMap.md │ ├── JUC集合——ConcurrentLinkedQueue.md │ ├── JUC集合——ConcurrentSkipListMap.md │ ├── JUC集合——ConcurrentSkipListSet.md │ ├── JUC集合——CopyOnWriteArrayList.md │ ├── JUC集合——CopyOnWriteArraySet.md │ ├── JUC集合——LinkedBlockingDeque.md │ ├── JUC集合——LinkedBlockingQueue.md │ ├── JUC集合——LinkedTransferQueue.md │ ├── JUC集合——PriorityQueue.md │ ├── JUC集合——框架.md │ └── assets │ │ ├── 1545396581057.png │ │ ├── 1545396928790.png │ │ ├── 1545397658950.png │ │ ├── 1545397749932.png │ │ ├── 1545397762923.png │ │ ├── 1545397804137.png │ │ ├── 1545397840614.png │ │ ├── 1545397887160.png │ │ ├── 1545398154642.png │ │ ├── 1545398582935.png │ │ ├── 1545398754822.png │ │ ├── 1545398767573.png │ │ ├── 1545398798974.png │ │ ├── 1545398845167.png │ │ ├── 1545398873596.png │ │ ├── 1545398924093.png │ │ ├── 1545404119873.png │ │ ├── 1545468789761.png │ │ ├── 1545469154761.png │ │ ├── 1545469782495.png │ │ ├── 1545469983372.png │ │ ├── 1545470151479.png │ │ ├── 1545548288576.png │ │ ├── 1545553939762.png │ │ ├── 1545919660660.png │ │ ├── 1545976117679.png │ │ ├── 1545976127224.png │ │ └── 1545976238915.png ├── Java中的锁.md ├── Java多线程基础知识.md ├── assets │ ├── 1548339052535.png │ ├── 1551447554369.png │ ├── 1551447737059.png │ ├── 1555751550402.png │ ├── 1559557555510.png │ └── 1559811884338.png ├── 图库 │ ├── ArrayList继承关系.png │ ├── HashMap——putVal方法.eddx │ ├── HashMap——putVal方法.png │ ├── Snipaste_2018-12-21_14-20-28.png │ ├── Snipaste_2018-12-21_14-21-11.png │ ├── Snipaste_2018-12-21_16-47-03.png │ ├── Snipaste_2018-12-21_16-51-17.png │ ├── Snipaste_2018-12-21_16-52-59.png │ ├── Snipaste_2018-12-21_18-34-38.png │ ├── Snipaste_2018-12-21_18-36-32.png │ ├── Snipaste_2018-12-21_18-37-15.png │ ├── Snipaste_2018-12-21_18-37-44.png │ ├── Snipaste_2018-12-21_18-38-46.png │ ├── Snipaste_2018-12-21_18-43-30.png │ ├── Snipaste_2018-12-21_18-43-35.png │ ├── Snipaste_2018-12-21_18-47-14.png │ ├── Snipaste_2018-12-21_18-48-04.png │ ├── Snipaste_2018-12-21_18-48-36.png │ ├── Snipaste_2018-12-21_18-52-55.png │ ├── Snipaste_2018-12-21_18-56-09.png │ ├── Snipaste_2018-12-21_18-57-30.png │ ├── Snipaste_2018-12-21_19-26-22.png │ ├── Snipaste_2018-12-21_19-30-28.png │ ├── Snipaste_2018-12-21_19-34-40.png │ ├── Snipaste_2018-12-21_19-34-49.png │ ├── Snipaste_2018-12-21_19-38-45.png │ ├── Snipaste_2018-12-21_19-39-02.png │ ├── Snipaste_2018-12-21_19-40-26.png │ ├── Snipaste_2018-12-21_19-40-36.png │ ├── Snipaste_2018-12-21_19-40-59.png │ ├── Snipaste_2018-12-21_19-48-51.png │ ├── Snipaste_2018-12-21_20-49-21.png │ ├── Snipaste_2018-12-21_20-49-28.png │ ├── Snipaste_2018-12-21_20-49-36.png │ ├── Snipaste_2018-12-21_20-55-22.png │ ├── Snipaste_2018-12-21_21-07-29.png │ ├── Snipaste_2018-12-21_21-09-07.png │ ├── Snipaste_2018-12-21_21-09-17.png │ ├── Snipaste_2018-12-21_21-10-00.png │ ├── Snipaste_2018-12-21_21-10-38.png │ ├── Snipaste_2018-12-21_21-11-23.png │ ├── Snipaste_2018-12-21_21-15-50.png │ ├── Snipaste_2018-12-21_21-22-52.png │ ├── Snipaste_2018-12-21_21-25-53.png │ ├── Snipaste_2018-12-21_21-26-03.png │ ├── Snipaste_2018-12-21_21-26-35.png │ ├── Snipaste_2018-12-21_21-27-22.png │ ├── Snipaste_2018-12-21_21-27-52.png │ ├── Snipaste_2018-12-21_21-28-41.png │ ├── Snipaste_2018-12-21_22-16-35.png │ ├── Snipaste_2018-12-21_22-22-25.png │ ├── Snipaste_2018-12-21_22-25-14.png │ ├── Snipaste_2018-12-21_22-29-10.png │ ├── Snipaste_2018-12-21_22-30-39.png │ ├── Snipaste_2018-12-21_22-31-14.png │ ├── Snipaste_2018-12-21_22-40-19.png │ ├── Snipaste_2018-12-21_22-41-24.png │ └── Snipaste_2018-12-21_22-55-17.png ├── 并发编程基础 │ ├── 1.md │ ├── 2.md │ ├── 3.md │ ├── 4.md │ ├── assets │ │ ├── 1559120626687.png │ │ ├── 1559201658664.png │ │ └── 1559201686917.png │ ├── 原子操作.md │ ├── 并发——锁.pdf │ └── 线程介绍.md ├── 线程池原理.md ├── 锁的膨胀过程.png └── 阻塞队列与非阻塞队列.md ├── 操作系统 └── 操作系统.md ├── 数据结构 ├── LCS、LIS、LICS.md ├── 位图法.md ├── 字符串排序.md ├── 排序.md ├── 排序.pdf ├── 查找.md ├── 树.md ├── 红黑树 │ ├── BST删除.eddx │ ├── assets │ │ ├── 1545804301946.png │ │ └── 1545810390091.png │ ├── 平衡二叉树的插入删除.eddx │ └── 红黑树.md └── 跳表.md ├── 智力题 └── 智力题.md ├── 海量数据处理 └── 海量数据处理.md ├── 计算机网络 ├── HTTP.md ├── assets │ ├── 1551084094722.png │ ├── 1551084304301.png │ ├── 1551085355690.png │ ├── 1551086857102.png │ ├── 1551086868181.png │ ├── 1551086936946.png │ ├── 1551087273159.png │ ├── 1551087364881.png │ ├── 1551091402770.png │ ├── 1551091797780.png │ ├── 1551092022139.png │ ├── 1551093997196.png │ ├── 1551095204273.png │ ├── 1551096881380.png │ ├── 1551096961208.png │ ├── 1551098195986.png │ ├── 1551099853175.png │ └── 1551100342853.png ├── 计算机网络.md └── 计算机网络.pdf ├── 设计模式 ├── assets │ ├── 1547979569144.png │ ├── 1548080740146.png │ ├── 1548081632615.png │ ├── 1548081639605.png │ ├── 1550999701408.png │ ├── 1551001017770.png │ ├── 1551002538396.png │ ├── 1551104273405.png │ └── 201919141715-3.png ├── images │ ├── Package abstractfactory.png │ ├── Package chainofresponsibility.png │ ├── Package command.png │ ├── Package factorymethod.png │ ├── Package memento.png │ ├── Package observer.png │ ├── Package simplefactory.png │ ├── Package state.png │ ├── Package templatemethod.png │ └── Singleton.png ├── 新建文本文档.txt └── 设计模式.md ├── 软件工程 └── 软件工程.md ├── 需要学习 ├── Dubbo+zookeper.md ├── GraphQL.md ├── Java8.md ├── Netty.md ├── RxJava.md ├── guava.md ├── nginx+Lua+redis.md └── webflux.md ├── 面筋 ├── 春招面筋.md └── 秋招面筋.md └── 项目 ├── JWT过期自动续期解决方案.md ├── assets ├── 1547038556115.png ├── 1551957761728.png ├── 乐优商城架构图-1551665325137.png └── 乐优商城架构图.png ├── 乐优商城面试总结.md ├── 学成在线.md ├── 接口限流.md ├── 日志系统.md ├── 电商网站详情页系统架构.md ├── 秒杀系统“减库存”设计思路.md └── 项目知识.md /.idea/Java面试宝典.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/inspectionProfiles/Project_Default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 36 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Git/Git.md: -------------------------------------------------------------------------------- 1 | # 一、git merge和git rebase的区别 2 | 3 | **rebase**会把你当前分支的 commit 放到公共分支的最后面,所以叫变基。就好像你从公共分支又重新拉出来这个分支一样。 4 | 5 | 举例:如果你从 master 拉了个feature分支出来,然后你提交了几个 commit,这个时候刚好有人把他开发的东西合并到 master 了,这个时候 master 就比你拉分支的时候多了几个 commit,如果这个时候你 rebase develop 的话,就会把你当前的几个 commit,放到那个人 commit 的后面。 6 | 7 | ![](http://mycsdnblog.work/201919141854-r.png) 8 | 9 | **merge** 会把公共分支和你当前的commit 合并在一起,形成一个新的 commit 提交 10 | 11 | ![](http://mycsdnblog.work/201919141855-X.png) 12 | 13 | 14 | 15 | git merge 操作合并分支会让两个分支的每一次提交都按照提交时间(并不是push时间)排序,并且会将两个分支的最新一次commit点进行合并成一个新的commit,最终的分支树呈现非整条线性直线的形式 16 | 17 | git rebase操作实际上是将当前执行rebase分支的所有基于原分支提交点之后的commit打散成一个一个的patch,并重新生成一个新的commit hash值,再次基于原分支目前最新的commit点上进行提交,并不根据两个分支上实际的每次提交的时间点排序,rebase完成后,切到基分支进行合并另一个分支时也不会生成一个新的commit点,可以保持整个分支树的完美线性 18 | 19 | -------------------------------------------------------------------------------- /JVM/assets/1547211103015.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547211103015.png -------------------------------------------------------------------------------- /JVM/assets/1547213596316.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547213596316.png -------------------------------------------------------------------------------- /JVM/assets/1547217765018.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547217765018.png -------------------------------------------------------------------------------- /JVM/assets/1547218853370.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547218853370.png -------------------------------------------------------------------------------- /JVM/assets/1547220419682.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547220419682.png -------------------------------------------------------------------------------- /JVM/assets/1547466178656.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547466178656.png -------------------------------------------------------------------------------- /JVM/assets/1547467164358.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547467164358.png -------------------------------------------------------------------------------- /JVM/assets/1547468174933.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547468174933.png -------------------------------------------------------------------------------- /JVM/assets/1547563769397.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1547563769397.png -------------------------------------------------------------------------------- /JVM/assets/1550822725879.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1550822725879.png -------------------------------------------------------------------------------- /JVM/assets/1550825623867.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1550825623867.png -------------------------------------------------------------------------------- /JVM/assets/1550825641737.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1550825641737.png -------------------------------------------------------------------------------- /JVM/assets/1550835491284.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1550835491284.png -------------------------------------------------------------------------------- /JVM/assets/1551143665881.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551143665881.png -------------------------------------------------------------------------------- /JVM/assets/1551143686368.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551143686368.png -------------------------------------------------------------------------------- /JVM/assets/1551143711681.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551143711681.png -------------------------------------------------------------------------------- /JVM/assets/1551144443784.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551144443784.png -------------------------------------------------------------------------------- /JVM/assets/1551146799869.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551146799869.png -------------------------------------------------------------------------------- /JVM/assets/1551146848389.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/1551146848389.png -------------------------------------------------------------------------------- /JVM/assets/wpsEB12.tmp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/wpsEB12.tmp.jpg -------------------------------------------------------------------------------- /JVM/assets/wpsF2F8.tmp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/wpsF2F8.tmp.jpg -------------------------------------------------------------------------------- /JVM/assets/wpsF87B.tmp.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/JVM/assets/wpsF87B.tmp.jpg -------------------------------------------------------------------------------- /Java基础/Java8新特性.md: -------------------------------------------------------------------------------- 1 | # 一、Lamada 2 | 3 | ## 1.1 实现匿名内部类 4 | 5 | ## 1.2 语法格式 6 | 7 | ```java 8 | /** 9 | * 总结:lambda表达式 10 | * 左侧:lambda表达式的参数列表————————接口的参数列表 11 | * 右侧:接口的方法实现 12 | * 13 | * 语法格式1:无参数无返回值方法 () -> System.out.println("runnable"); 14 | * 语法格式2:一个参数,无返回值 (x) -> System.out.println(x) 15 | * 语法格式3:一个参数,括号可以不写 16 | * 语法格式4:多个参数,有返回值,lambda有多条语句,有返回值 使用{} 17 | * 语法格式5:多个参数,有返回值,lambda中只有一条语句,return可以省略 18 | * 语法格式6:lambda参数列表中的参数类型可以省略不写,因为JVM编译器,通过上下文推断出数据类型,即“类型推断” 19 | */ 20 | ``` 21 | 22 | ## 1.3 Java内置的四大核心函数式接口 23 | 24 | 消费类型接口:Consumer 25 | 26 | 供给型接口:Supplier 27 | 28 | 函数型接口:Function 29 | 30 | 断定型接口:Predicate 31 | 32 | ![](http://mycsdnblog.work/201919121408-c.png) 33 | 34 | ## 1.4 lambda表达式的作用 35 | 36 | **不仅仅是语法糖** 37 | 38 | lambda带给我们的,不仅仅只是语法上的简洁,而是一种新的编程方式,可以**将函数当做参数传递**,有点C#里面委托的意思。 39 | 40 | > 委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递 41 | > 42 | > public delegate int MethodtDelegate(int x, int y);表示有两个参数,并返回int型。 43 | 44 | 所谓“函数参数”,虽然本质上也是用内部类实现。但是,那又怎样呢?我们完全可以将其理解为函数参数来简化我们的编程,不能将lambda简单理解为少写代码的语法糖。 45 | 46 | **函数式接口:只有一个方法的接口** 47 | 48 | 使用此类接口的时候(Runable,Comparator),要么我们定义一个类来实现该接口,要么使用匿名内部类。对于匿名内部类,编译器会为每一个匿名内部类创建相应的类文件。一般的程序,往往回调接口会有很多。这样就会生成很多的类文件,因为类在使用之前需要加载类文件并进行验证,这个过程就会影响应用的性能。 49 | 50 | # 二、流 51 | 52 | 流是数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。“集合讲的是数据,流讲的是计算”。 53 | 54 | 注意: 55 | 56 | Stream自己不会存储元素 57 | 58 | Stream不会改变源对象。相反,他们会返回一个持有结果的新Stream。 59 | 60 | Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才去执行。 61 | 62 | ## 2.1 操作步骤 63 | 64 | 1. 创建流 65 | 66 | 2. 中间操作 67 | 68 | ``` 69 | /** 70 | * 中间操作 71 | * 72 | * 筛选与切片 73 | * filter——接收lambda,从流中排除某些元素 74 | * limit——截断流,使用元素不超过给定数量 75 | * skip——跳过元素 76 | * distinct——筛选 77 | */ 78 | 79 | /** 80 | * map 接收lambda,将元素转换成其它形式或提取信息。接收一个函数作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素 81 | * flatMap 接收一个函数作为参数,将流中的每个值都转换成另一个流,然后把所有流连接成一个流 82 | */ 83 | 84 | /** 85 | * 排序 86 | * sorted()自然排序 87 | * sorted(Comparator com)定制排序 88 | */ 89 | ``` 90 | 91 | 3. 终止操作 92 | 93 | ``` 94 | /** 95 | * Stream的终止操作: 96 | * allMatch 检查是否匹配所有元素 97 | * anyMatch 检查是否至少匹配一个元素 98 | * noneMatch 检查是否没有匹配所有元素 99 | * findFirst 返回第一个元素 100 | * findAny 返回当前流中的任意元素 101 | * count 返回流中的元素个数 102 | * max 返回流中的最大值 103 | * min 返回流中的最小值 104 | */ 105 | ``` 106 | 107 | **多个中间操作可以连接起来形成一个流水线,除非流水线上触发终止操作,否则中间操作不会执行任何的处理!而在终止操作时一次性全部处理,称为“惰性求值”。内部迭代** 108 | 109 | ## 2.2 并行流和顺序流 110 | 111 | Fork/Join框架 112 | 113 | 将大任务进行拆分(fork)成若干个小任务(不可拆分时),再将一个个的小任务的运算结果进行join汇总 114 | 115 | ![](http://mycsdnblog.work/201919121632-v.png) 116 | 117 | 采用“工作窃取”模式: 118 | 119 | 当执行新的任务时它可以将其拆分成更小的任务执行,并将小任务加到线程队列中,然后再从一个随机线程的队列中偷一个并把它放到自己的队列中 120 | 121 | 相对于一般的线程池实现,fork/join框架的优势体现在对其中包含的任务的处理方式上,在一般的线程池中,如果一个线程正在执行的任务由于某些原因无法继续运行,那么该线程会处于等待状态,而在fork/join框架实现中,如果某个子问题由于等待另一个子问题的完成而无法继续执行,那么处理该子问题的线程会主动寻找其它尚未运行的子问题来执行。这种方式减少了线程等待的时间,提高了性能。 122 | 123 | Java8中将并行进行了优化,我们可以很容易的对数据进行并行操作。Stream API可以声明性地通过parrallel()与sequential()在并行流与顺序流之间进行切换。 124 | 125 | ForkJoin框架采用的是“工作窃取模式”,传统线程在处理任务时,假设有一个大任务被分解成了20个小任务,并由四个线程A,B,C,D处理,理论上来讲一个线程处理5个任务,每个线程的任务都放在一个队列中,当B,C,D的任务都处理完了,而A因为某些原因阻塞在了第二个小任务上,那么B,C,D都需要等待A处理完成,此时A处理完第二个任务后还有三个任务需要处理,可想而知,这样CPU的利用率很低。而ForkJoin采取的模式是,当B,C,D都处理完了,而A还阻塞在第二个任务时,B会从A的任务队列的末尾偷取一个任务过来自己处理,C和D也会从A的任务队列的末尾偷一个任务,这样就相当于B,C,D额外帮A分担了一些任务,提高了CPU的利用率。 126 | 127 | 2、ForkJoin框架的使用方式, 128 | 129 | - 编写计算类继承RecursiveTask接口并重写T compute方法; 130 | - 使用fork方法拆分任务,join合并计算结果; 131 | - 使用ForkJoinPool调用invoke方法来执行一个任务。 132 | 133 | -------------------------------------------------------------------------------- /Java基础/Java9新特性.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/Java9新特性.md -------------------------------------------------------------------------------- /Java基础/Java网络编程.md: -------------------------------------------------------------------------------- 1 | # 一、IO的方式 2 | 3 | IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO。 4 | 5 | ## 1.1 BIO 6 | 7 | BIO 就是传统的 [java.io](http://java.io/) 包,它是基于流模型实现的,交互的方式是同步、阻塞方式,也就是说在读入输入流或者输出流时,在读写动作完成之前,线程会一直阻塞在那里,它们之间的调用时可靠的线性顺序。它的有点就是代码比较简单、直观;缺点就是 IO 的效率和扩展性很低,容易成为应用性能瓶颈。 8 | 9 | ### 1.1.1 客户端 10 | 11 | ```java 12 | package com.example.exe1; 13 | 14 | 15 | import java.io.IOException; 16 | import java.io.InputStream; 17 | import java.io.OutputStream; 18 | import java.net.Socket; 19 | 20 | /** 21 | * @Author: 98050 22 | * @Time: 2019-08-31 14:44 23 | * @Feature: 客户端 24 | */ 25 | public class TcpClient { 26 | 27 | public static void main(String[] args) throws IOException { 28 | Socket socket = new Socket("127.0.0.1",6666); 29 | OutputStream outputStream = socket.getOutputStream(); 30 | outputStream.write("你好服务器,我是客户端1".getBytes()); 31 | 32 | InputStream inputStream = socket.getInputStream(); 33 | byte[] bytes = new byte[1024]; 34 | int len = inputStream.read(bytes); 35 | System.out.println(new String(bytes,0,len)); 36 | inputStream.close(); 37 | socket.close(); 38 | } 39 | } 40 | ``` 41 | 42 | ### 1.1.2 服务器端 43 | 44 | ```java 45 | package com.example.exe1; 46 | 47 | import java.io.IOException; 48 | import java.net.ServerSocket; 49 | import java.net.Socket; 50 | 51 | /** 52 | * @Author: 98050 53 | * @Time: 2019-08-31 14:50 54 | * @Feature: 55 | */ 56 | public class TcpServer { 57 | 58 | public static void main(String[] args) throws IOException { 59 | ServerSocket serverSocket = new ServerSocket(6666); 60 | Socket socket; 61 | while (true) { 62 | socket = serverSocket.accept(); 63 | ServerThread thread = new ServerThread(socket); 64 | thread.start(); 65 | } 66 | } 67 | } 68 | ``` 69 | 70 | ```java 71 | package com.example.exe1; 72 | 73 | import java.io.IOException; 74 | import java.io.InputStream; 75 | import java.io.OutputStream; 76 | import java.net.Socket; 77 | 78 | /** 79 | * @Author: 98050 80 | * @Time: 2019-08-31 15:22 81 | * @Feature: 82 | */ 83 | public class ServerThread extends Thread{ 84 | 85 | Socket socket; 86 | 87 | public ServerThread(Socket socket) { 88 | this.socket = socket; 89 | } 90 | 91 | @Override 92 | public void run() { 93 | InputStream inputStream = null; 94 | try { 95 | inputStream = socket.getInputStream(); 96 | byte[] bytes = new byte[1024]; 97 | int len = inputStream.read(bytes); 98 | System.out.println(socket.getInetAddress() + new String(bytes, 0, len)); 99 | OutputStream outputStream = socket.getOutputStream(); 100 | outputStream.write("收到谢谢".getBytes()); 101 | } catch (IOException e) { 102 | e.printStackTrace(); 103 | }finally { 104 | try { 105 | socket.close(); 106 | } catch (IOException e) { 107 | e.printStackTrace(); 108 | } 109 | } 110 | } 111 | } 112 | ``` 113 | 114 | ## 1.2 NIO 115 | 116 | NIO基于Reactor,当socket有流可读或可写入socket时,操作系统会相应的通知引用程序进行处理,应用再将流读取到缓冲区或写入操作系统。 也就是说,这个时候,已经不是一个连接就要对应一个处理线程了,而是有效的请求,对应一个线程,当连接没有数据时,是没有工作线程来处理的。 117 | 118 | BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。 119 | 120 | **NIO的最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。** 121 | 122 | HTTP/1.1出现后,有了Http长连接,这样除了超时和指明特定关闭的http header外,这个链接是一直打开的状态的,这样在NIO处理中可以进一步的进化,在后端资源中可以实现资源池或者队列,当请求来的话,开启的线程把请求和请求数据传送给后端资源池或者队列里面就返回,并且在全局的地方保持住这个现场(哪个连接的哪个请求等),这样前面的线程还是可以去接受其他的请求,而后端的应用的处理只需要执行队列里面的就可以了,这样请求处理和后端应用是异步的.当后端处理完,到全局地方得到现场,产生响应,这个就实现了异步处理。 123 | 124 | ![](http://mycsdnblog.work/201919142024-w.png) 125 | 126 | 首先,Requester方通过Selector.open()创建了一个Selector准备好了调度角色。 127 | 128 | 创建了SocketChannel(ServerSocketChannel) 并注册到Selector中,通过设置key(SelectionKey)告诉调度者所应该关注的连接请求。 129 | 130 | 阻塞,Selector阻塞在select操作中,如果发现有Channel发生连接请求,就会唤醒处理请求。 131 | 132 | ## 1.3 AIO 133 | 134 | 异步非阻塞I/O,服务器实现模式为一个有效请求一个线程,**客户端的IO请求都是由操作系统先完成了再通知服务器用其启动线程进行处理**。AIO方式适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,jdk1.7开始支持。 135 | 136 | ## 1.4 总结 137 | 138 | 139 | 140 | ## 1.5 Java对BIO、NIO、AIO的支持 141 | 142 | - Java BIO : 同步并阻塞,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 143 | - Java NIO : 同步非阻塞,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程进行处理。 144 | - Java AIO(NIO.2) : 异步非阻塞,服务器实现模式为一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理, 145 | 146 | # 二、一个端口能建立几个TCP连接 147 | 148 | 为什么一个端口能建立多个TCP连接,同一个端口也就是说 server ip和server port 是不变的。那么只要[client ip 和 client port]不相同就可以了。能保证接唯一标识[server ip, server port, client ip, client port]的唯一性。 149 | 150 | 一个端口能建立多个UDP连接么? 151 | 152 | UPD本身就是无连接的。所以不存在什么多个UDP连接。只是,服务端接收UDP数据需要bind一个端口。一个SOCKET只能绑定到一个端口。 153 | 154 | # 三、多个线程可以监听同一个端口吗? 155 | 156 | 多个线程可以监听同一个端口。 157 | 158 | 但是,我们通常不这样做,因为,这样做了,不光多个线程能够共用这个端口,多个进程也能共用这个端口,我们无法感应那个进程在用这个端口。 159 | 160 | 最恐怖的事情是,共用相同端口的进线程,它们不会得到相同的数据,也就是说,一个客户端连接上来,发送数据,这些数据,会混乱的被多个线程处理。 161 | 162 | -------------------------------------------------------------------------------- /Java基础/assets/1550994028985.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1550994028985.png -------------------------------------------------------------------------------- /Java基础/assets/1550994192470.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1550994192470.png -------------------------------------------------------------------------------- /Java基础/assets/1550994395358.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1550994395358.png -------------------------------------------------------------------------------- /Java基础/assets/1551191608732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1551191608732.png -------------------------------------------------------------------------------- /Java基础/assets/1551592963527.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1551592963527.png -------------------------------------------------------------------------------- /Java基础/assets/1561973717974.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java基础/assets/1561973717974.png -------------------------------------------------------------------------------- /Java集合类/Java集合——Stack.md: -------------------------------------------------------------------------------- 1 | # 一、Stack介绍 2 | 3 | Stack是栈。它的特性是:**先进后出**(FILO, First In Last Out)。 4 | 5 | java工具包中的Stack是继承于Vector(矢量队列)的,由于Vector是通过数组实现的,这就意味着,**Stack也是通过数组实现的**,**而非链表**。当然,我们也可以将LinkedList当作栈来使用! 6 | 7 | ![](http://mycsdnblog.work/201919271441-x.png) 8 | 9 | 重要API: 10 | 11 | ![](http://mycsdnblog.work/201919271441-9.png) 12 | 13 | # 二、源码分析 14 | 15 | ## 2.1 push 16 | 17 | ```java 18 | public E push(E item) { 19 | addElement(item); 20 | 21 | return item; 22 | } 23 | ``` 24 | 25 | 调用父类中的addElement方法 26 | 27 | ```java 28 | public synchronized void addElement(E obj) { 29 | modCount++; 30 | ensureCapacityHelper(elementCount + 1); 31 | elementData[elementCount++] = obj; 32 | } 33 | ``` 34 | 35 | ## 2.2 peek 36 | 37 | ```java 38 | public synchronized E peek() { 39 | int len = size(); 40 | 41 | if (len == 0) 42 | throw new EmptyStackException(); 43 | return elementAt(len - 1); 44 | } 45 | ``` 46 | ```java 47 | public synchronized E elementAt(int index) { 48 | if (index >= elementCount) { 49 | throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount); 50 | } 51 | 52 | return elementData(index); 53 | } 54 | ``` 55 | 56 | ```java 57 | E elementData(int index) { 58 | return (E) elementData[index]; 59 | } 60 | ``` 61 | 62 | ## 2.3 pop 63 | 64 | ```java 65 | public synchronized E pop() { 66 | E obj; 67 | int len = size(); 68 | 69 | obj = peek(); 70 | removeElementAt(len - 1); 71 | 72 | return obj; 73 | } 74 | ``` 75 | 76 | 调用父类中的removeElementAt方法 77 | 78 | ```java 79 | public synchronized void removeElementAt(int index) { 80 | modCount++; 81 | if (index >= elementCount) { 82 | throw new ArrayIndexOutOfBoundsException(index + " >= " + 83 | elementCount); 84 | } 85 | else if (index < 0) { 86 | throw new ArrayIndexOutOfBoundsException(index); 87 | } 88 | int j = elementCount - index - 1; 89 | if (j > 0) { 90 | System.arraycopy(elementData, index + 1, elementData, index, j); 91 | } 92 | elementCount--; 93 | elementData[elementCount] = null; /* to let gc do its work */ 94 | } 95 | ``` 96 | 97 | ## 2.4 empty 98 | 99 | ```java 100 | public boolean empty() { 101 | return size() == 0; 102 | } 103 | ``` 104 | 105 | -------------------------------------------------------------------------------- /Java集合类/Java集合——TreeMap.md: -------------------------------------------------------------------------------- 1 | # 一、介绍 2 | 3 | TreeMap 是一个**有序的key-value集合**,它是通过红黑树实现的。 4 | TreeMap **继承于AbstractMap**,所以它是一个Map,即一个key-value集合。 5 | TreeMap 实现了NavigableMap接口,意味着它**支持一系列的导航方法。**比如返回有序的key集合。 6 | TreeMap 实现了Cloneable接口,意味着**它能被克隆**。 7 | TreeMap 实现了java.io.Serializable接口,意味着**它支持序列化**。 8 | 9 | TreeMap基于**红黑树(Red-Black tree)实现**。该映射根据**其键的自然顺序进行排序**,或者根据**创建映射时提供的 Comparator 进行排序**,具体取决于使用的构造方法。 10 | 11 | TreeMap的基本操作 containsKey、get、put 和 remove 的时间复杂度是 log(n) 。 12 | 13 | 另外,TreeMap是**非同步**的。 它的iterator 方法返回的**迭代器是fail-fastl**的。 14 | 15 | > **fail-fast 机制是java集合(Collection)中的一种错误机制。**当多个线程对同一个集合的内容进行操作时,就可能会产生fail-fast事件。例如:当某一个线程A通过iterator去遍历某集合的过程中,若该集合的内容被其他线程所改变了;那么线程A访问集合时,就会抛出ConcurrentModificationException异常,产生fail-fast事件。 16 | 17 | 构造函数: 18 | 19 | ```java 20 | // 默认构造函数。使用该构造函数,TreeMap中的元素按照自然排序进行排列。 21 | TreeMap() 22 | 23 | // 创建的TreeMap包含Map 24 | TreeMap(Map copyFrom) 25 | 26 | // 指定Tree的比较器 27 | TreeMap(Comparator comparator) 28 | 29 | // 创建的TreeSet包含copyFrom 30 | TreeMap(SortedMap copyFrom) 31 | ``` 32 | 33 | # 二、数据结构 34 | 35 | ![](http://mycsdnblog.work/201919281812-U.png) 36 | 37 | 从图中可以看出: 38 | (1) TreeMap实现继承于AbstractMap,并且实现了NavigableMap接口。 39 | (2) TreeMap的本质是R-B Tree(红黑树),它包含几个重要的成员变量: root, size, comparator。 40 | 41 | - root 是红黑数的根节点。它是Entry类型,Entry是红黑数的节点,它包含了红黑数的6个基本组成成分:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(颜色)。Entry节点根据key进行排序,Entry节点包含的内容为value。 42 | - 红黑数排序时,**根据Entry中的key进行排序**;Entry中的key比较大小是根据比较器comparator来进行判断的。 43 | - size是红黑数中节点的个数。 44 | 45 | # 三、源码解析 46 | 47 | # 四、遍历方式 48 | 49 | # 五、示例 -------------------------------------------------------------------------------- /Java集合类/Java集合——TreeSet.md: -------------------------------------------------------------------------------- 1 | 一、介绍 2 | 3 | 二、数据结构 4 | 5 | 三、源码解析 6 | 7 | 四、遍历方式 8 | 9 | 五、示例 -------------------------------------------------------------------------------- /Java集合类/Java集合——Vector.md: -------------------------------------------------------------------------------- 1 | # 一、介绍 2 | 3 | Vector 是**矢量队列**,它是JDK1.0版本添加的类。继承于AbstractList,实现了List, RandomAccess, Cloneable这些接口。 4 | Vector 继承了AbstractList,实现了List;所以,**它是一个队列,支持相关的添加、删除、修改、遍历等功能**。 5 | Vector 实现了RandmoAccess接口,即**提供了随机访问功能**。RandmoAccess是java中用来被List实现,为List提供快速访问功能的。在Vector中,我们即可以通过元素的序号快速获取元素对象;这就是快速随机访问。 6 | Vector 实现了Cloneable接口,即实现clone()函数。它能被克隆。 7 | 8 | 和ArrayList不同,**Vector中的操作是线程安全的**。 9 | 10 | # 二、数据结构 11 | 12 | ![](http://mycsdnblog.work/201919122150-x.png) 13 | 14 | Vector的数据结构和ArrayList差不多,它包含了3个成员变量:elementData , elementCount, capacityIncrement。 15 | 16 | (01) elementData 是"Object[]类型的数组",它保存了添加到Vector中的元素。elementData是个动态数组,如果初始化Vector时,没指定动态数组的>大小,则使用默认大小10。随着Vector中元素的增加,Vector的容量也会动态增长,capacityIncrement是与容量增长相关的增长系数,具体的增长方式,请参考源码分析中的ensureCapacity()函数。 17 | 18 | (02) elementCount 是动态数组的实际大小。 19 | 20 | (03) capacityIncrement 是动态数组的增长系数。如果在创建Vector时,指定了capacityIncrement的大小;则,每次当Vector中动态数组容量增加时,增加的大小都是capacityIncrement。 21 | 22 | # 三、源码解析 23 | 24 | ## 3.1 添加 25 | 26 | ![](http://mycsdnblog.work/201919122152-Z.png) 27 | 28 | 因为加了synchronized关键字,所以添加操作是线程安全的。添加元素前通过调用`ensureCapacityHelper`方法来保证容量大小: 29 | 30 | ![](http://mycsdnblog.work/201919122155-W.png) 31 | 32 | ![](http://mycsdnblog.work/201919122156-l.png) 33 | 34 | 如果数组越界,说明数组放不下了,需要进行扩容,`grow`方法: 35 | 36 | ![](http://mycsdnblog.work/201919122157-x.png) 37 | 38 | 如果指定了`capacityIncrement`增长系数的话,就做相应的扩大,否则扩容一倍 39 | 40 | ## 3.2 删除 41 | 42 | ![](http://mycsdnblog.work/201919122158-W.png) 43 | 44 | 主要方法就是`removeElement`: 45 | 46 | ![](http://mycsdnblog.work/201919122158-l.png) 47 | 48 | 使用synchronized关键字,所以线程安全。找到要移除元素的下标,然后判断位置是否合理,合理的话就进行移除。 49 | 50 | ## 3.3 获取 51 | 52 | ![](http://mycsdnblog.work/201919122200-t.png) 53 | 54 | 获取的方法上也加了synchronized,验证范围是否合理,合理的话返回对应的值。 55 | 56 | # 四、遍历方式 57 | 58 | - 迭代器 59 | - 随机访问 60 | - 增强for循环 61 | - **Enumeration**遍历 62 | 63 | # 五、示例 -------------------------------------------------------------------------------- /Java集合类/assets/1545373231486.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545373231486.png -------------------------------------------------------------------------------- /Java集合类/assets/1545373273549.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545373273549.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382028006.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382028006.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382296775.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382296775.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382402926.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382402926.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382500758.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382500758.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382564275.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382564275.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382588262.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382588262.png -------------------------------------------------------------------------------- /Java集合类/assets/1545382622346.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545382622346.png -------------------------------------------------------------------------------- /Java集合类/assets/1545383369548.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545383369548.png -------------------------------------------------------------------------------- /Java集合类/assets/1545388481935.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545388481935.png -------------------------------------------------------------------------------- /Java集合类/assets/1545388594643.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545388594643.png -------------------------------------------------------------------------------- /Java集合类/assets/1545388638099.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545388638099.png -------------------------------------------------------------------------------- /Java集合类/assets/1545388667403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545388667403.png -------------------------------------------------------------------------------- /Java集合类/assets/1545388729610.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545388729610.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389017751.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389017751.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389307255.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389307255.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389320129.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389320129.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389576804.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389576804.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389772766.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389772766.png -------------------------------------------------------------------------------- /Java集合类/assets/1545389853050.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545389853050.png -------------------------------------------------------------------------------- /Java集合类/assets/1545391584232.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545391584232.png -------------------------------------------------------------------------------- /Java集合类/assets/1545391830662.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545391830662.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392082121.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392082121.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392093353.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392093353.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392334936.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392334936.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392354319.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392354319.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392442561.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392442561.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392460658.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392460658.png -------------------------------------------------------------------------------- /Java集合类/assets/1545392933952.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545392933952.png -------------------------------------------------------------------------------- /Java集合类/assets/1545401798571.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545401798571.png -------------------------------------------------------------------------------- /Java集合类/assets/1545402146851.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545402146851.png -------------------------------------------------------------------------------- /Java集合类/assets/1545402318913.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545402318913.png -------------------------------------------------------------------------------- /Java集合类/assets/1545402552154.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545402552154.png -------------------------------------------------------------------------------- /Java集合类/assets/1545402644510.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545402644510.png -------------------------------------------------------------------------------- /Java集合类/assets/1545402676747.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545402676747.png -------------------------------------------------------------------------------- /Java集合类/assets/1545403220901.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545403220901.png -------------------------------------------------------------------------------- /Java集合类/assets/1545403286365.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545403286365.png -------------------------------------------------------------------------------- /Java集合类/assets/1545547808198.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545547808198.png -------------------------------------------------------------------------------- /Java集合类/assets/1545548231371.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545548231371.png -------------------------------------------------------------------------------- /Java集合类/assets/1545549283999.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545549283999.png -------------------------------------------------------------------------------- /Java集合类/assets/1545549518834.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545549518834.png -------------------------------------------------------------------------------- /Java集合类/assets/1545551281396.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545551281396.png -------------------------------------------------------------------------------- /Java集合类/assets/1545553423888.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545553423888.png -------------------------------------------------------------------------------- /Java集合类/assets/1545556394817.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545556394817.png -------------------------------------------------------------------------------- /Java集合类/assets/1545557010001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545557010001.png -------------------------------------------------------------------------------- /Java集合类/assets/1545828744891.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545828744891.png -------------------------------------------------------------------------------- /Java集合类/assets/1545901568538.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1545901568538.png -------------------------------------------------------------------------------- /Java集合类/assets/1550627367494.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1550627367494.png -------------------------------------------------------------------------------- /Java集合类/assets/1550628222261.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1550628222261.png -------------------------------------------------------------------------------- /Java集合类/assets/1550628241555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1550628241555.png -------------------------------------------------------------------------------- /Java集合类/assets/1551188876539.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1551188876539.png -------------------------------------------------------------------------------- /Java集合类/assets/1551189103471.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1551189103471.png -------------------------------------------------------------------------------- /Java集合类/assets/1551189233419.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1551189233419.png -------------------------------------------------------------------------------- /Java集合类/assets/1551189400227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1551189400227.png -------------------------------------------------------------------------------- /Java集合类/assets/1551189416163.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1551189416163.png -------------------------------------------------------------------------------- /Java集合类/assets/1558524788238.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1558524788238.png -------------------------------------------------------------------------------- /Java集合类/assets/1558525322177.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1558525322177.png -------------------------------------------------------------------------------- /Java集合类/assets/1558529309195.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Java集合类/assets/1558529309195.png -------------------------------------------------------------------------------- /Kubernetes/assets/1593172424925.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Kubernetes/assets/1593172424925.png -------------------------------------------------------------------------------- /Kubernetes/assets/1593173010870.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Kubernetes/assets/1593173010870.png -------------------------------------------------------------------------------- /Kubernetes/assets/1593174370946.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Kubernetes/assets/1593174370946.png -------------------------------------------------------------------------------- /Kubernetes/assets/1593174473066.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Kubernetes/assets/1593174473066.png -------------------------------------------------------------------------------- /Kubernetes/assets/1593174566864.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Kubernetes/assets/1593174566864.png -------------------------------------------------------------------------------- /Kubernetes/资料/mytomcat-rc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ReplicationController 3 | metadata: 4 | name: mytomcat 5 | spec: 6 | replicas: 2 7 | selector: 8 | app: mytomcat 9 | template: 10 | metadata: 11 | labels: 12 | app: mytomcat 13 | spec: 14 | containers: 15 | - name: mytomcat 16 | image: tomcat:7-jre7 17 | ports: 18 | - containerPort: 8080 -------------------------------------------------------------------------------- /Kubernetes/资料/mytomcat-svc.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: mytomcat 5 | spec: 6 | type: NodePort 7 | ports: 8 | - port: 8080 9 | nodePort: 40001 10 | selector: 11 | app: mytomcat -------------------------------------------------------------------------------- /Linux/Linux2.md: -------------------------------------------------------------------------------- 1 | # 一、进程管理 2 | 3 | ## 1.1 查看进程 4 | 5 | 查看某个时间点的进程信息 6 | 7 | 示例一:查看自己的进程 8 | 9 | ``` 10 | # ps -l 11 | ``` 12 | 13 | 示例二:查看系统所有进程 14 | 15 | ``` 16 | # ps aux 17 | ``` 18 | 19 | 示例三:查看特定的进程 20 | 21 | ``` 22 | # ps aux | grep threadx 23 | ``` 24 | 25 | ## 1.2 pstree 26 | 27 | 查看进程树 28 | 29 | 示例:查看所有进程树 30 | 31 | ``` 32 | # pstree -A 33 | ``` 34 | 35 | ## 1.3 top 36 | 37 | 实时显示进程信息 38 | 39 | 示例:两秒钟刷新一次 40 | 41 | ``` 42 | # top -d 2 43 | ``` 44 | 45 | ## 1.4 netstat 46 | 47 | 查看占用端口的进程 48 | 49 | 示例:查看特定端口的进程 50 | 51 | ``` 52 | # netstat -anp | grep port 53 | ``` 54 | 55 | ## 1.5 孤儿进程 56 | 57 | 一个父进程退出,而它的一个或多个子进程还在运行,那么这些子进程将成为孤儿进程。 58 | 59 | 孤儿进程将被 init 进程(进程号为 1)所收养,并由 init 进程对它们完成状态收集工作。 60 | 61 | 由于孤儿进程会被 init 进程收养,所以孤儿进程不会对系统造成危害。 62 | 63 | ## 1.6 僵尸进程 64 | 65 | 僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。 66 | 67 | 一个子进程的进程描述符在子进程退出时不会释放,只有当父进程通过 wait() 或 waitpid() 获取了子进程信息后才会释放。如果子进程退出,而父进程并没有调用 wait() 或 waitpid(),那么子进程的进程描述符仍然保存在系统中,这种进程称之为僵尸进程。 68 | 69 | 僵尸进程通过 ps 命令显示出来的状态为 Z(zombie)。 70 | 71 | **系统所能使用的进程号是有限的,如果产生大量僵尸进程,将因为没有可用的进程号而导致系统不能产生新的进程。** 72 | 73 | **要消灭系统中大量的僵尸进程,只需要将其父进程杀死,此时僵尸进程就会变成孤儿进程,从而被 init 所收养,这样 init 就会释放所有的僵尸进程所占有的资源,从而结束僵尸进程。** 74 | 75 | ------ 76 | 77 | 总结: 78 | 79 | **孤儿进程:一个父进程退出,而它的一个或多个子进程还在运行,那么那些子进程将成为孤儿进程。孤儿进程将被init进程(进程号为1)所收养,并由init进程对它们完成状态收集工作。** 80 | 81 | **僵尸进程:一个进程使用fork创建子进程,如果子进程退出,而父进程并没有调用wait或waitpid获取子进程的状态信息,那么子进程的进程描述符仍然保存在系统中。这种进程称之为僵死进程。** 82 | 83 | ## 1.7 fork 84 | 85 | 首先,先来讲一下fork之后,发生了什么事情。 86 | 87 | 由fork创建的新进程被称为子进程(child process)。**该函数被调用一次,但返回两次。两次返回的区别是子进程的返回值是0**,而**父进程的返回值则是新进程(子进程)的进程 id。将子进程id返回给父进程的理由是:因为一个进程的子进程可以多于一个,没有一个函数使一个进程可以获得其所有子进程的进程id**。对子进程来说,之所以fork返回0给它,是因为它随时可以调用**getpid()来获取自己的pid;也可以调用getppid()来获取父进程的id**。(进程id 0总是由交换进程使用,所以一个子进程的进程id不可能为0 )。 88 | 89 | fork之后,**操作系统会复制一个与父进程完全相同的子进程,虽说是父子关系,但是在操作系统看来,他们更像兄弟关系,这2个进程共享代码空间,但是数据空间是互相独立的,子进程数据空间中的内容是父进程的完整拷贝,指令指针也完全相同,子进程拥有父进程当前运行到的位置**(**两进程的程序计数器pc值相同,也就是说,子进程是从fork返回处开始执行的**),但有一点不同,如果fork成功,子进程中fork的返回值是0,父进程中fork的返回值是子进程的进程号,如果fork不成功,父进程会返回错误。 90 | 可以这样想象,2个进程一直同时运行,而且步调一致,在fork之后,他们分别作不同的工作,也就是分岔了。这也是fork为什么叫fork的原因 91 | 92 | 至于那一个最先运行,可能与操作系统(调度算法)有关,而且这个问题在实际应用中并不重要,如果需要父子进程协同,可以通过原语的办法解决。 93 | 94 | fork()函数用于从一个已经存在的进程内创建一个新的进程,新的进程称为“子进程”,相应地称创建子进程的进程为“父进程”。 95 | 96 | 使用fork()函数得到的子进程是父进程的复制品,子进程完全复制了父进程的资源,包括进程上下文、代码区、数据区、堆区、栈区、内存信息、打开文件的文件描述符、信号处理函数、进程优先级、进程组号、当前工作目录、根目录、资源限制和控制终端等信息,**而子进程与父进程的区别有进程号、资源使用情况和计时器等**。 97 | 98 | -------------------------------------------------------------------------------- /Maven/assets/1562154899070.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Maven/assets/1562154899070.png -------------------------------------------------------------------------------- /Maven/assets/1562155173376.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Maven/assets/1562155173376.png -------------------------------------------------------------------------------- /Maven/assets/1562155253276.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Maven/assets/1562155253276.png -------------------------------------------------------------------------------- /Maven/assets/1562155455144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Maven/assets/1562155455144.png -------------------------------------------------------------------------------- /Mysql/Mysql七种join.md: -------------------------------------------------------------------------------- 1 | # 一、准备工作 2 | 3 | ## 1.1 建表 4 | 5 | ```mysql 6 | CREATE TABLE tbl_dept( 7 | id INT(11) NOT NULL AUTO_INCREMENT, 8 | deptName VARCHAR(30), 9 | locAdd VARCHAR(40), 10 | PRIMARY KEY(id) 11 | )ENGINE=INNODB CHARSET = utf8; 12 | 13 | CREATE TABLE tbl_emp( 14 | id INT(11) NOT NULL AUTO_INCREMENT, 15 | NAME VARCHAR(30), 16 | deptId INT(11), 17 | PRIMARY KEY(id), 18 | FOREIGN KEY tbl_emp(deptId) REFERENCES tbl_dept(id) 19 | )ENGINE=INNODB CHARSET = utf8; 20 | ``` 21 | 22 | ## 1.2 插入数据 23 | 24 | ```mysql 25 | INSERT INTO tbl_dept(deptName,locAdd) VALUES('RD',11); 26 | INSERT INTO tbl_dept(deptName,locAdd) VALUES('HR',12); 27 | INSERT INTO tbl_dept(deptName,locAdd) VALUES('MK',13); 28 | INSERT INTO tbl_dept(deptName,locAdd) VALUES('MIS',14); 29 | INSERT INTO tbl_dept(deptName,locAdd) VALUES('FD',15); 30 | 31 | INSERT INTO tbl_emp(NAME,deptId) VALUES('z3',1); 32 | INSERT INTO tbl_emp(NAME,deptId) VALUES('z4',1); 33 | INSERT INTO tbl_emp(NAME,deptId) VALUES('z5',1); 34 | 35 | INSERT INTO tbl_emp(NAME,deptId) VALUES('w5',2); 36 | INSERT INTO tbl_emp(NAME,deptId) VALUES('w6',2); 37 | 38 | INSERT INTO tbl_emp(NAME,deptId) VALUES('s7',3); 39 | 40 | INSERT INTO tbl_emp(NAME,deptId) VALUES('s8',4); 41 | ``` 42 | 43 | # 二、连接 44 | 45 | ## *2.1 内连接 46 | 47 | ![](http://mycsdnblog.work/201919042008-J.png) 48 | 49 | ```mysql 50 | SELECT 51 | * 52 | FROM 53 | tbl_dept a 54 | INNER JOIN tbl_emp b ON a.id = b.deptId; 55 | ``` 56 | 57 | 或者 58 | 59 | ```mysql 60 | SELECT 61 | * 62 | FROM 63 | tbl_dept, 64 | tbl_emp 65 | WHERE 66 | tbl_dept.id = tbl_emp.deptId; 67 | ``` 68 | 69 | 结果: 70 | 71 | ![](http://mycsdnblog.work/201919042016-a.png) 72 | 73 | ## 2.2 外连接 74 | 75 | ### 2.2.1 左外连接 76 | 77 | ![](http://mycsdnblog.work/201919042021-X.png) 78 | 79 | ```mysql 80 | SELECT 81 | * 82 | FROM 83 | tbl_dept a 84 | LEFT JOIN tbl_emp b ON a.id = b.deptId; 85 | ``` 86 | 87 | 或者 88 | 89 | ```mysql 90 | SELECT 91 | * 92 | FROM 93 | tbl_dept a 94 | LEFT OUTER JOIN tbl_emp b ON a.id = b.deptId; 95 | ``` 96 | 97 | 结果: 98 | 99 | ![](http://mycsdnblog.work/201919042026-a.png) 100 | 101 | ### 2.2.2 右外连接 102 | 103 | ![](http://mycsdnblog.work/201919042031-Y.png) 104 | 105 | ```mysql 106 | SELECT 107 | * 108 | FROM 109 | tbl_dept a 110 | RIGHT JOIN tbl_emp b ON a.id = b.deptId; 111 | ``` 112 | 113 | 或者: 114 | 115 | ```mysql 116 | SELECT 117 | * 118 | FROM 119 | tbl_dept a 120 | RIGHT OUTER JOIN tbl_emp b ON a.id = b.deptId; 121 | ``` 122 | 123 | 结果: 124 | 125 | ![](http://mycsdnblog.work/201919042033-m.png) 126 | 127 | ### 2.2.3 全连接 128 | 129 | ![](http://mycsdnblog.work/201919042042-i.png) 130 | 131 | mysql不支持,用其他方案代替 132 | 133 | ## 2.3 自连接 134 | 135 | 自连接,连接的两个表都是同一个表,同样可以由内连接,外连接各种组合方式,按实际应用去组合 136 | 137 | ```mysql 138 | SELECT 139 | * 140 | FROM 141 | tbl_dept a 142 | LEFT JOIN tbl_dept b ON a.id = b.id; 143 | ``` 144 | 145 | 结果: 146 | 147 | ![](http://mycsdnblog.work/201919042055-f.png) 148 | 149 | ## 2.4 笛卡儿积 150 | 151 | A x B 152 | 153 | ```mysql 154 | SELECT 155 | * 156 | FROM 157 | tbl_dept 158 | CROSS JOIN tbl_emp; 159 | ``` 160 | 161 | 结果: 162 | 163 | | id | deptName | locAdd | id(1) | NAME | deptId | 164 | | ---- | -------- | ------ | ----- | ---- | :----- | 165 | | 1 | RD | 11 | 1 | z3 | 1 | 166 | | 2 | HR | 12 | 1 | z3 | 1 | 167 | | 3 | MK | 13 | 1 | z3 | 1 | 168 | | 4 | MIS | 14 | 1 | z3 | 1 | 169 | | 5 | FD | 15 | 1 | z3 | 1 | 170 | | 1 | RD | 11 | 2 | z4 | 1 | 171 | | 2 | HR | 12 | 2 | z4 | 1 | 172 | | 3 | MK | 13 | 2 | z4 | 1 | 173 | | 4 | MIS | 14 | 2 | z4 | 1 | 174 | | 5 | FD | 15 | 2 | z4 | 1 | 175 | | 1 | RD | 11 | 3 | z5 | 1 | 176 | | 2 | HR | 12 | 3 | z5 | 1 | 177 | | 3 | MK | 13 | 3 | z5 | 1 | 178 | | 4 | MIS | 14 | 3 | z5 | 1 | 179 | | 5 | FD | 15 | 3 | z5 | 1 | 180 | | 1 | RD | 11 | 4 | w5 | 2 | 181 | | 2 | HR | 12 | 4 | w5 | 2 | 182 | | 3 | MK | 13 | 4 | w5 | 2 | 183 | | 4 | MIS | 14 | 4 | w5 | 2 | 184 | | 5 | FD | 15 | 4 | w5 | 2 | 185 | | 1 | RD | 11 | 5 | w6 | 2 | 186 | | 2 | HR | 12 | 5 | w6 | 2 | 187 | | 3 | MK | 13 | 5 | w6 | 2 | 188 | | 4 | MIS | 14 | 5 | w6 | 2 | 189 | | 5 | FD | 15 | 5 | w6 | 2 | 190 | | 1 | RD | 11 | 6 | s7 | 3 | 191 | | 2 | HR | 12 | 6 | s7 | 3 | 192 | | 3 | MK | 13 | 6 | s7 | 3 | 193 | | 4 | MIS | 14 | 6 | s7 | 3 | 194 | | 5 | FD | 15 | 6 | s7 | 3 | 195 | | 1 | RD | 11 | 7 | s8 | 4 | 196 | | 2 | HR | 12 | 7 | s8 | 4 | 197 | | 3 | MK | 13 | 7 | s8 | 4 | 198 | | 4 | MIS | 14 | 7 | s8 | 4 | 199 | | 5 | FD | 15 | 7 | s8 | 4 | -------------------------------------------------------------------------------- /Mysql/assets/1550386270485.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550386270485.png -------------------------------------------------------------------------------- /Mysql/assets/1550399006096.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550399006096.png -------------------------------------------------------------------------------- /Mysql/assets/1550400143482.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550400143482.png -------------------------------------------------------------------------------- /Mysql/assets/1550467448201.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550467448201.png -------------------------------------------------------------------------------- /Mysql/assets/1550468251532.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550468251532.png -------------------------------------------------------------------------------- /Mysql/assets/1550468294210.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550468294210.png -------------------------------------------------------------------------------- /Mysql/assets/1550728150375.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728150375.png -------------------------------------------------------------------------------- /Mysql/assets/1550728228269.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728228269.png -------------------------------------------------------------------------------- /Mysql/assets/1550728239905.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728239905.png -------------------------------------------------------------------------------- /Mysql/assets/1550728619714.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728619714.png -------------------------------------------------------------------------------- /Mysql/assets/1550728646391.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728646391.png -------------------------------------------------------------------------------- /Mysql/assets/1550728862668.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728862668.png -------------------------------------------------------------------------------- /Mysql/assets/1550728956375.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550728956375.png -------------------------------------------------------------------------------- /Mysql/assets/1550729396796.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550729396796.png -------------------------------------------------------------------------------- /Mysql/assets/1550729590333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550729590333.png -------------------------------------------------------------------------------- /Mysql/assets/1550729615581.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550729615581.png -------------------------------------------------------------------------------- /Mysql/assets/1550730034562.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1550730034562.png -------------------------------------------------------------------------------- /Mysql/assets/1566890429079.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1566890429079.png -------------------------------------------------------------------------------- /Mysql/assets/1567417612154.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Mysql/assets/1567417612154.png -------------------------------------------------------------------------------- /Mysql/数据库基本理论.md: -------------------------------------------------------------------------------- 1 | ### 一、关系型数据库 2 | 3 | **关系型数据库:指采用了关系模型来组织数据的数据库。 关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。** 4 | 5 | 关系模型中常用的概念: 6 | 关系:一张二维表,每个关系都具有一个关系名,也就是表名 7 | 元组:二维表中的一行,在数据库中被称为记录 8 | 属性:二维表中的一列,在数据库中被称为字段 9 | 域:属性的取值范围,也就是数据库中某一列的取值限制 10 | 关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成 11 | 关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, ... ... ,属性N),在数据库中成为表结构 12 | 13 | #### 1.1 关系型数据库的优点 14 | 15 | **1.容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解 ** 16 | 17 | **2.使用方便:通用的SQL语言使得操作关系型数据库非常方便 ** 18 | 19 | **3.易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率** 20 | 21 | #### 1.2 关系型数据库存在的问题 22 | 23 | **1.网站的用户并发性非常高,往往达到每秒上万次读写请求,对于传统关系型数据库来说,硬盘I/O是一个很大的瓶颈 ** 24 | 25 | **2.网站每天产生的数据量是巨大的,对于关系型数据库来说,在一张包含海量数据的表中查询,效率是非常低的 ** 26 | 27 | **3.在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server和app server那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。当需要对数据库系统进行升级和扩展时,往往需要停机维护和数据迁移。 ** 28 | 29 | **4.性能欠佳:在关系型数据库中,导致性能欠佳的最主要原因是多表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询。为了保证数据库的ACID特性,必须尽量按照其要求的范式进行设计,关系型数据库中的表都是存储一个格式化的数据结构。** 30 | 31 | ### 二、非关系型数据库 32 | 33 | **非关系型数据库:指非关系型的,分布式的,且一般不保证遵循ACID原则的数据存储系统。** 34 | 35 | #### 2.1 非关系型数据库结构 36 | 37 | **非关系型数据库以键值对存储,且结构不固定,每一个元组可以有不一样的字段,每个元组可以根据需要增加一些自己的键值对,不局限于固定的结构,可以减少一些时间和空间的开销。** 38 | 39 | #### 2.2 优点 40 | 41 | **1.用户可以根据需要去添加自己需要的字段,为了获取用户的不同信息,不像关系型数据库中,要对多表进行关联查询。仅需要根据id取出相应的value就可以完成查询。 ** 42 | 43 | **2.适用于SNS(Social Networking Services)中,例如facebook,微博。系统的升级,功能的增加,往往意味着数据结构巨大变动,这一点关系型数据库难以应付,需要新的结构化数据存储。由于不可能用一种数据结构化存储应付所有的新的需求,因此,非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。** 44 | 45 | #### 2.3 不足 46 | 47 | **只适合存储一些较为简单的数据,对于需要进行较复杂查询的数据,关系型数据库显的更为合适。不适合持久存储海量数据** 48 | 49 | #### 2.4 非关系型数据库的分类 50 | 51 | **非关系型数据库都是针对某些特定的应用需求出现的,因此,对于该类应用,具有极高的性能。依据结构化方法以及应用场合的不同,主要分为以下几类:** 52 | 53 | ##### 2.4.1 面向高性能并发读写的key-value数据库 54 | 55 | **key-value数据库的主要特点是具有极高的并发读写性能** 56 | `Key-value`数据库是一种以键值对存储数据的一种数据库,类似`Java`中的`map`。可以将整个数据库理解为一个大的`map`,每个键都会对应一个唯一的值。 57 | **主流代表为Redis** 58 | 59 | ##### 2.4.2 面向海量数据访问的面向文档数据库 60 | 61 | **这类数据库的主要特点是在海量的数据中可以快速的查询数据** 62 | 文档存储通常使用内部表示法,可以直接在应用程序中处理,主要是`JSON`。`JSON`文档也可以作为纯文本存储在键值存储或关系数据库系统中。 63 | **主流代表为MongoDB** 64 | 65 | ##### 2.4.3 面向搜索数据内容的搜索引擎 66 | 67 | **搜索引擎是专门用于搜索数据内容的NoSQL数据库管理系统。** 68 | 主要是用于对海量数据进行近实时的处理和分析处理,可用于机器学习和数据挖掘 69 | **主流代表为Elasticsearch** 70 | 71 | ##### 2.4.4 面向可扩展性的分布式数据库 72 | 73 | **这类数据库的主要特点是具有很强的可拓展性** 74 | 普通的关系型数据库都是以行为单位来存储数据的,擅长以行为单位的读入处理,比如特定条件数据的获取。因此,关系型数据库也被成为面向行的数据库。相反,面向列的数据库是以列为单位来存储数据的,擅长以列为单位读入数据。 75 | **这类数据库想解决的问题就是传统数据库存在可扩展性上的缺陷,这类数据库可以适应数据量的增加以及数据结构的变化,将数据存储在记录中,能够容纳大量动态列。由于列名和记录键不是固定的,并且由于记录可能有数十亿列,因此可扩展性存储可以看作是二维键值存储。** 76 | **主流代表为Cassandra,HBase,Microsoft Azure Cosmos DB, Datastax Enterprise和Accumulo** 77 | 78 | ### 三、CAP理论 79 | 80 | **NoSQL的基本需求就是支持分布式存储,严格一致性与可用性需要互相取舍** 81 | CAP理论:**一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(分区容错性)**三个基本需求,并且最多只能满足其中的两项。对于一个分布式系统来说,分区容错是基本需求,否则不能称之为分布式系统,因此需要在C和A之间寻求平衡 82 | **C(Consistency)一致性 一致性是指更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。与ACID的C完全不同 A(Availability)可用性 可用性是指服务一直可用,而且是正常响应时间。 P(Partition tolerance)分区容错性 分区容错性是指分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。** 83 | 84 | ### 四、关系型与非关系型数据库的比较 85 | 86 | **1.成本:Nosql数据库简单易部署,基本都是开源软件,不需要像使用Oracle那样花费大量成本购买使用,相比关系型数据库价格便宜。 ** 87 | 88 | **2.查询速度:Nosql数据库将数据存储于缓存之中,而且不需要经过SQL层的解析,关系型数据库将数据存储在硬盘中,自然查询速度远不及Nosql数据库。 ** 89 | 90 | **3.存储数据的格式:Nosql的存储格式是key,value形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。 ** 91 | 92 | **4.扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。Nosql基于键值对,数据之间没有耦合性,所以非常容易水平扩展。 ** 93 | 94 | **5.持久存储:Nosql不使用于持久存储,海量数据的持久存储,还是需要关系型数据库 ** 95 | 96 | **6.数据一致性:非关系型数据库一般强调的是数据最终一致性,不像关系型数据库一样强调数据的强一致性,从非关系型数据库中读到的有可能还是处于一个中间态的数据, Nosql不提供对事务的处理。** 97 | 98 | -------------------------------------------------------------------------------- /Mysql/数据库实战.md: -------------------------------------------------------------------------------- 1 | > 查找最晚入职员工的所有信息 2 | 3 | 子查询:select * from employees where hire_date = (select max(hire_date) from employees); 4 | 5 | 排序、分页:select * from employees order by hire_date desc limit 0,1; 6 | 7 | > 查找入职员工时间排名倒数第三的员工所有信息 8 | 9 | select * from employees where hire_date = (select hire_date from employees order by hire_date desc limit 2,1); 10 | 11 | > 查找各个部门当前(to_date='9999-01-01')领导当前薪水详情以及其对应部门编号dept_no 12 | 13 | SELECT s.*,d.dept_no FROM salaries s,dept_manager d WHERE s.emp_no = d.emp_no AND s.to_date = '9999-01-01' AND d.to_date = '9999-01-01'; 14 | 15 | > 查找所有已经分配部门的员工的last_name和first_name 16 | 17 | select e.last_name,e.first_name,dept_no 18 | from dept_emp,employees e 19 | where dept_emp.emp_no = e.emp_no; 20 | 21 | > 查找所有员工的last_name和first_name以及对应部门编号dept_no,也包括展示没有分配具体部门的员工 22 | 23 | select last_name,first_name,dept_no 24 | from employees left join dept_emp on(dept_emp.emp_no = employees.emp_no); 25 | 26 | > 查找所有员工入职时候的薪水情况,给出emp_no以及salary, 并按照emp_no进行逆序 27 | 28 | SELECT e.emp_no,salary 29 | FROM employees e,salaries s 30 | WHERE e.emp_no = s.emp_no AND e.hire_date = s.from_date 31 | ORDER BY e.emp_no DESC; 32 | 33 | > 查找薪水涨幅超过15次的员工号emp_no以及其对应的涨幅次数t 34 | 35 | SELECT emp_no,COUNT(DISTINCT salary) AS t 36 | FROM salaries 37 | GROUP BY emp_no 38 | HAVING t > 15; 39 | 40 | > 找出所有员工当前(to_date='9999-01-01')具体的薪水salary情况,对于相同的薪水只显示一次,并按照逆序显示 41 | 42 | SELECT DISTINCT salary 43 | FROM salaries 44 | WHERE to_date = '9999-01-01' 45 | ORDER BY salary DESC; 46 | 47 | > 获取所有部门当前manager的当前薪水情况,给出dept_no, emp_no以及salary,当前表示to_date='9999-01-01' 48 | 49 | SELECT d.dept_no,d.emp_no,s.salary 50 | FROM dept_manager d,salaries s 51 | WHERE d.to_date = '9999-01-01' AND s.to_date = '9999-01-01' AND d.emp_no = s.emp_no; 52 | 53 | > 获取所有非manager的员工emp_no 54 | 55 | 子查询: 56 | 57 | SELECT emp_no 58 | FROM employees 59 | WHERE emp_no NOT IN( 60 | SELECT emp_no 61 | FROM dept_manager 62 | ); 63 | 64 | 表连接: 65 | 66 | SELECT employees.emp_no 67 | FROM employees LEFT JOIN dept_manager ON employees.emp_no = dept_manager.emp_no 68 | WHERE dept_manager.emp_no IS NULL; 69 | 70 | > 获取所有员工当前的manager,如果当前的manager是自己的话结果不显示,当前表示to_date='9999-01-01'。 71 | > 结果第一列给出当前员工的emp_no,第二列给出其manager对应的manager_no。 72 | 73 | SELECT dept_emp.emp_no,dept_manager.emp_no AS manager_no 74 | FROM dept_emp LEFT JOIN dept_manager ON (dept_emp.dept_no = dept_manager.dept_no) 75 | WHERE dept_emp.emp_no != dept_manager.emp_no AND dept_emp.to_date ='9999-01-01' AND dept_manager.to_date ='9999-01-01'; 76 | 77 | > 获取所有部门中当前员工薪水最高的相关信息,给出dept_no, emp_no以及其对应的salary 78 | 79 | SELECT dept_emp.dept_no,dept_emp.emp_no,MAX(salary) AS salary 80 | FROM dept_emp LEFT JOIN salaries ON dept_emp.emp_no = salaries.emp_no 81 | WHERE dept_emp.to_date = '9999-01-01' AND salaries.to_date = '9999-01-01' 82 | GROUP BY dept_emp.dept_no; 83 | 84 | > 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。 85 | 86 | SELECT title,COUNT(*) AS t 87 | FROM titles 88 | GROUP BY title; 89 | 90 | > 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t。 91 | > 注意对于重复的emp_no进行忽略。 92 | 93 | SELECT title,COUNT(DISTINCT emp_no) AS t 94 | FROM titles 95 | GROUP BY title 96 | HAVING t >= 2; 97 | 98 | > 查找employees表所有emp_no为奇数,且last_name不为Mary的员工信息,并按照hire_date逆序排列 99 | 100 | SELECT * 101 | FROM employees 102 | WHERE emp_no % 2 != 0 AND last_name != 'Mary' 103 | ORDER BY hire_date DESC 104 | 105 | > 统计出当前各个title类型对应的员工当前薪水对应的平均工资。结果给出title以及平均工资avg。 106 | 107 | SELECT title,AVG(salary) AS avg 108 | FROM salaries s,titles t 109 | WHERE s.emp_no = t.emp_no AND s.to_date='9999-01-01' AND t.to_date = '9999-01-01' 110 | GROUP BY title; 111 | 112 | > 获取当前(to_date='9999-01-01')薪水第二多的员工的emp_no以及其对应的薪水salary 113 | 114 | SELECT emp_no,salary 115 | FROM salaries 116 | WHERE to_date='9999-01-01' 117 | ORDER BY salary DESC LIMIT 1,1; 118 | 119 | > 查找当前薪水(to_date='9999-01-01')排名第二多的员工编号emp_no、薪水salary、last_name以及first_name,不准使用order by 120 | 121 | SELECT e.emp_no,MAX(s.salary) AS salary,e.last_name,e.first_name 122 | FROM employees e,salaries s 123 | WHERE e.emp_no = s.emp_no AND s.to_date = '9999-01-01' AND s.salary < ( 124 | SELECT MAX(salary) 125 | FROM salaries 126 | ); 127 | 128 | > 查找所有员工的last_name和first_name以及对应的dept_name,也包括暂时没有分配部门的员工 129 | 130 | SELECT last_name,first_name,dept_name 131 | FROM (employees LEFT JOIN dept_emp ON (employees.emp_no = dept_emp.emp_no)) LEFT JOIN departments ON (dept_emp.dept_no = departments.dept_no); 132 | 133 | > 查找员工编号emp_no为10001其自入职以来的薪水salary涨幅值growth 134 | 135 | SELECT (MAX(salary) - MIN(salary)) AS growth 136 | FROM salaries 137 | WHERE emp_no = '10001'; 138 | 139 | > 查找所有员工自入职以来的薪水涨幅情况,给出员工编号emp_no以及其对应的薪水涨幅growth,并按照growth进行升序 140 | 141 | SELECT now.emp_no, (now.salary - old.salary) growth 142 | FROM (SELECT e.emp_no,s.salary FROM employees e LEFT JOIN salaries s ON (e.emp_no = s.emp_no) WHERE s.to_date ='9999-01-01') AS now 143 | INNER JOIN (SELECT e.emp_no,s.salary FROM employees e LEFT JOIN salaries s ON (e.emp_no = s.emp_no) WHERE s.from_date = e.hire_date) AS old ON (old.emp_no = now.emp_no) 144 | ORDER BY growth -------------------------------------------------------------------------------- /Mysql/订单系统分库分表.md: -------------------------------------------------------------------------------- 1 | # 一、订单数据如何划分 2 | 3 | 我们可以将订单数据划分成两大类型:分别是热数据和冷数据。 4 | 5 | - 热数据:3个月内的订单数据,查询实时性较高; 6 | - 冷数据A:3个月 ~ 12个月前的订单数据,查询频率不高; 7 | - 冷数据B:1年前的订单数据,几乎不会查询,只有偶尔的查询需求; 8 | 9 | 可能这里有个疑惑为什么要将冷数据分成两类,因为根据实际场景需求,用户基本不会去查看1年前的数据,如果将这部分数据还存储在db中,那么成本会非常高,而且也不便于维护。另外如果真遇到有个别用户需要查看1年前的订单信息,可以让用户走离线数据查看。 10 | 11 | 对于这三类数据的存储,目前规划如下: 12 | 13 | - 热数据: 使用mysql进行存储,当然需要分库分表; 14 | - 冷数据A: 对于这类数据可以存储在ES中,利用搜索引擎的特性基本上也可以做到比较快的查询; 15 | - 冷数据B: 对于这类不经常查询的数据,可以存放到Hive中; 16 | 17 | # 二、如何分库分表 18 | 19 | 通常一般的电商平台,包含了用户、商品、订单等几大模块,简单的做法是在同一个库中分别建4张表,如下图所示: 20 | 21 | ![](http://mycsdnblog.work/201919122252-k.png) 22 | 23 | 但是随着业务的提升,将所有业务都放在一个库中已经变得越来越难以维护,因此我们建议,将不同业务放在不同的库中,如下图所示: 24 | 25 | ![](http://mycsdnblog.work/201919122253-o.png) 26 | 27 | 由图中我们可以看出,我们将不同的业务放到不同的库中,将原来所有压力由同一个库中分散到不同的库中,提升了系统的吞吐量。 28 | 29 | ## 2.1 分表策略 30 | 31 | 我们以订单表为例,在订单表中,订单id肯定是不可重复的,因此将该字段当做shard key 是非常适合的,其他表类似。 32 | 33 | 我们假设预估单个库需要分配100个表满足我们的业务需求,我们可以简单的取模计算出订单在哪个子表中,例如: order_id % 100, 34 | 35 | ![](http://mycsdnblog.work/201919130937-K.png) 36 | 37 | 这时候可能会有人问了,如果我根据order_id 进行分表规则,但是我想根据user_id 查询相应的订单,不是定位不到哪个子表了吗,的确是这样,一旦确定shard key,就只能根据shard key定位到子表进而查询该子表下的数据;**如果确实想根据user_id 去查询相关订单,那应该将shard key设置为user_id, 那分表规则也相应的变更为: user_id % 100;** 38 | 39 | ## 2.2 分库策略 40 | 41 | 数据库分表能够解决单表数据量很大的时候数据查询的效率问题,但是无法给数据库的并发操作带来效率上的提高,因为分表的实质还是在一个数据库上进行的操作,很容易受数据库IO性能的限制。 42 | 43 | 因此,如何将数据库IO性能的问题平均分配出来,很显然将数据进行分库操作可以很好地解决单台数据库的性能问题。 44 | 45 | 分库策略与分表策略的实现很相似,最简单的都是可以通过取模的方式进行路由。 46 | 47 | 我们还是以order表举例, 48 | 49 | 例如:order_id % 库容量, 50 | 51 | 如果order_id 不是整数类型,可以先hash 在进行取模, 52 | 53 | 例如: hash(order_id) % 库容量 54 | 55 | ## 2.3 结合 56 | 57 | 数据库分表可以解决单表海量数据的查询性能问题,分库可以解决单台数据库的并发访问压力问题。有时候,我们需要同时考虑这两个问题,因此,我们既需要对单表进行分表操作,还需要进行分库操作,以便同时扩展系统的并发处理能力和提升单表的查询性能,就是我们使用到的分库分表。 58 | 59 | 如果使用分库分表结合使用的话,不能简单进行order_id 取模操作,需要加一个中间变量用来打散到不同的子表,公式如下: 60 | 61 | ![](http://mycsdnblog.work/201919130943-0.png) 62 | 63 | 中间变量 = shard key %(库数量*单个库的表数量) 64 | 65 | 库序号 = 取整(中间变量/单个库的表数量) 66 | 67 | 表序号 = 中间变量%单个库的表数量 68 | 69 | 例如:数据库有10个,每一个库中有100个数据表,用户的order_id=1001,按照上述的路由策略,可得: 70 | 71 | ![](http://mycsdnblog.work/201919130944-b.png) 72 | 73 | 这样的话,对于order_id=1001,将被路由到第1个数据库的第2个表中(索引0 代表1,依次类推)。 74 | 75 | ![](http://mycsdnblog.work/201919130945-x.png) 76 | 77 | # 三、MyCat 78 | 79 | # 四、shardingjdb -------------------------------------------------------------------------------- /ORM/assets/1550934048277.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1550934048277.png -------------------------------------------------------------------------------- /ORM/assets/1550934127858.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1550934127858.png -------------------------------------------------------------------------------- /ORM/assets/1550976038601.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1550976038601.png -------------------------------------------------------------------------------- /ORM/assets/1551851951248.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1551851951248.png -------------------------------------------------------------------------------- /ORM/assets/1551851960403.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1551851960403.png -------------------------------------------------------------------------------- /ORM/assets/1551852796288.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1551852796288.png -------------------------------------------------------------------------------- /ORM/assets/1551852827882.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/ORM/assets/1551852827882.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 创建时间:2018‎年‎12‎月‎19‎日 2 | 3 | # 完成时间:2019年09月30日 4 | 5 | # 记录了在半年时间内为找工作而学习的Java相关内容 6 | 7 | # TODO:继续补充内容+整理 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /RabbitMQ/assets/1562315466839.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/RabbitMQ/assets/1562315466839.png -------------------------------------------------------------------------------- /Spring Cloud Alibaba/assets/1566555914717.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring Cloud Alibaba/assets/1566555914717.png -------------------------------------------------------------------------------- /Spring Cloud Alibaba/assets/1566556778593.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring Cloud Alibaba/assets/1566556778593.png -------------------------------------------------------------------------------- /Spring Cloud Alibaba/assets/1566558467634.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring Cloud Alibaba/assets/1566558467634.png -------------------------------------------------------------------------------- /Spring/Java反射机制.md: -------------------------------------------------------------------------------- 1 | # 一、什么是Java反射 2 | 3 | 就是类正在运行,动态获取这个类的所有信息。 4 | 5 | # 二、反射机制的作用 6 | 7 | 反编译:.class-->.java 8 | 9 | 通过反射机制访问java对象的属性,方法,构造方法等; 10 | 11 | # 三、应用 12 | 13 | Jdbc 加载驱动----- 14 | 15 | Spring IOC 16 | 17 | 框架 18 | 19 | # 四、反射机制获取类的三种方法 20 | 21 | ```java 22 | public class Test { 23 | 24 | public static void main(String[] args) throws ClassNotFoundException { 25 | Class class1 = Class.forName("Emplyee"); 26 | Class class2 = Employee.class; 27 | Class class3 = new Employee().getClass(); 28 | } 29 | } 30 | ``` 31 | 32 | # 五、API 33 | 34 | | 方法名称 | 作用 | 35 | | --------------------- | ------------------ | 36 | | getDeclaredMethods [] | 获取该类的所有方法 | 37 | | getReturnType() | 获取该类的返回值 | 38 | | getParameterTypes() | 获取传入参数 | 39 | | getDeclaredFields() | 获取该类的所有字段 | 40 | | setAccessible | 允许访问私有成员 | 41 | 42 | # 六、禁止使用反射机制初始化 43 | 44 | 将构造函数为私有化 45 | 46 | -------------------------------------------------------------------------------- /Spring/Spring中的设计模式.md: -------------------------------------------------------------------------------- 1 | # 一、简单工厂 2 | 3 | **当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建的细节。** 4 | 5 | Spring的IoC容器 6 | 7 | # 二、工厂模式 8 | 9 | **定义了一个创建对象的接口,但由子类决定要实例化哪个类。工厂方法把实例化操作推迟到子类。** 10 | 11 | **Spring中的BeanFactory就是工厂模式的体现,根据传入一个唯一的标识来获得Bean对象,但是否是在传入参数后创建还是传入参数前创建这个要根据具体情况来定。** 12 | 13 | # 三、单例模式 14 | 15 | Spring IoC容器中的Bean都是单例的 16 | 17 | # 四、适配器模式 18 | 19 | Spring中在对于AOP的处理中有Adapter模式的例子 20 | 21 | 使用的Advice(通知)来增强被代理类的功能 22 | 23 | # 五、包装器 24 | 25 | # 六、代理设计模式 26 | 27 | 动态代理和CGLIB代理 28 | 29 | # 七、策略模式 30 | 31 | 在策略模式中,创建表示各种策略的对象和一个行为随着策略对象改变而改变的 context 对象。策略对象改变 context 对象的执行算法。 32 | 33 | Spring 在初始化Bean的时候,有两种策略:反射和CGLIB 34 | 35 | # 八、观察者模式 36 | 37 | 当对象间存在一对多关系时,则使用观察者模式(Observer Pattern)。比如,当一个对象被修改时,则会自动通知它的依赖对象。 38 | 39 | # 九、模板方法 40 | 41 | - 声明接口 42 | - 来一个默认抽象实现 43 | - 具体实现 44 | 45 | 如果后期要进行扩展,怎么办? 46 | 47 | 加钩子函数 48 | 49 | # 十、命令模式 50 | 51 | HandlerExecutionChain的实现 52 | 53 | -------------------------------------------------------------------------------- /Spring/Spring面试题.md: -------------------------------------------------------------------------------- 1 | # 1、BeanFactory 和 FactoryBean? 2 | 3 | 区别:BeanFactory是个Factory,也就是IOC容器或对象工厂,FactoryBean是个Bean。在Spring中,**所有的Bean都是由BeanFactory(也就是IOC容器)来进行管理的**。但对FactoryBean而言,**这个Bean不是简单的Bean,而是一个能生产或者修饰对象生成的工厂Bean,它的实现与设计模式中的工厂模式和修饰器模式类似** 4 | 5 | > **BeanFactory** 6 | 7 | BeanFactory,以Factory结尾,表示它是一个工厂类(接口), **它负责生产和管理bean的一个工厂**。在Spring中,**BeanFactory是IOC容器的核心接口,它的职责包括:实例化、定位、配置应用程序中的对象及建立这些对象间的依赖。BeanFactory只是个接口,并不是IOC容器的具体实现,但是Spring容器给出了很多种实现,如 DefaultListableBeanFactory、XmlBeanFactory、ApplicationContext等,其中XmlBeanFactory就是常用的一个,该实现将以XML方式描述组成应用的对象及对象间的依赖关系**。 8 | 9 | > **FactoryBean** 10 | 11 | **一般情况下,Spring通过反射机制利用的class属性指定实现类实例化Bean,在某些情况下,实例化Bean过程比较复杂,如果按照传统的方式,则需要在中提供大量的配置信息。配置方式的灵活性是受限的,这时采用编码的方式可能会得到一个简单的方案。Spring为此提供了一个org.springframework.bean.factory.FactoryBean的工厂类接口,用户可以通过实现该接口定制实例化Bean的逻辑。FactoryBean接口对于Spring框架来说占用重要的地位,Spring自身就提供了70多个FactoryBean的实现**。 12 | 13 | # 2、BeanFactory 和 ApplicationContext? 14 | 15 | 我们一般称 BeanFactory 为 IoC 容器,而称 ApplicationContext 为应用上下文或 Spring 容器 。 16 | 17 | BeanFactory 是 Spring 框架的基础设施,面向 Spring 本身; ApplicationContext 面向使用 Spring 框架的开发者,几乎所有的应用场合都可以直接使用 ApplicationContext。 18 | 19 | 1.BeanFactroy采用的是延迟加载形式来注入Bean的,即只有在使用到某个Bean时(调用getBean()),才对该Bean进行加载实例化,这样,我们就不能发现一些存在的Spring的配置问题。而ApplicationContext则相反,它是在容器启动时,一次性创建了所有的Bean。这样,在容器启动时,我们就可以发现Spring中存在的配置错误。 相对于基本的BeanFactory,ApplicationContext 唯一的不足是占用内存空间。当应用程序配置Bean较多时,程序启动较慢。 20 | 21 | BeanFacotry延迟加载,如果Bean的某一个属性没有注入,BeanFacotry加载后,直至第一次使用调用getBean方法才会抛出异常;而ApplicationContext则在初始化自身是检验,这样有利于检查所依赖属性是否注入;所以通常情况下我们选择使用 ApplicationContext。 22 | 应用上下文则会在上下文启动后预载入所有的单实例Bean。通过预载入单实例bean ,确保当你需要的时候,你就不用等待,因为它们已经创建好了。 23 | 24 | 2.BeanFactory和ApplicationContext都支持BeanPostProcessor、BeanFactoryPostProcessor的使用,但两者之间的区别是:BeanFactory需要手动注册,而ApplicationContext则是自动注册。(Applicationcontext比 beanFactory 加入了一些更好使用的功能。而且 beanFactory 的许多功能需要通过编程实现而 Applicationcontext 可以通过配置实现。比如后处理 bean , Applicationcontext 直接配置在配置文件即可而 beanFactory 这要在代码中显示的写出来才可以被容器识别。 ) 25 | 26 | 3.beanFactory主要是面对与 spring 框架的基础设施,面对 spring 自己。而 Applicationcontex 主要面对与 spring 使用的开发者。基本都会使用 Applicationcontex 并非 beanFactory 。 27 | 28 | # 3、Spring 如何保证 Controller 并发的安全? 29 | 30 | Spring 多线程请求过来调用的Controller对象都是一个,而不是一个请求过来就创建一个Controller对象。 31 | 32 | **并发的安全?** 33 | 原因就在于Controller对象是单例的,那么如果不小心在类中定义了类变量,那么这个类变量是被所有请求共享的,这可能会造成多个请求修改该变量的值,出现与预期结果不符合的异常 34 | 35 | **那有没有办法让Controller不以单例而以每次请求都重新创建的形式存在呢?** 36 | 答案是当然可以,只需要在类上添加注解@Scope("prototype")即可,这样每次请求调用的类都是重新生成的(每次生成会影响效率) 37 | 38 | 虽然这样可以解决问题,但增加了时间成本,总让人不爽,还有其他方法么?答案是肯定的! 39 | 40 | 使用**ThreadLocal**来保存类变量,将类变量保存在线程的变量域中,让不同的请求隔离开来。 41 | 42 | # 4、Spring Bean的生命周期 43 | 44 | - Bean实例的创建 45 | - 为Bean实例设置属性 46 | - 调用Bean的初始化方法 47 | - 应用可以通过IOC容器使用Bean 48 | - 当容器关闭时,调用Bean的销毁方法 49 | 50 | # 5、Spring Bean的作用域 51 | 52 | ![1550994028985](assets/1550994028985.png) 53 | 54 | # 6、Spring 解决循环注入的原理? 55 | 56 | Spring为了解决单例的循环依赖问题,使用了**三级缓存**。 57 | 58 | 这三级缓存分别指: 59 | 60 | - singletonFactories : 单例对象工厂的cache 61 | - earlySingletonObjects :提前暴光的单例对象的Cache 62 | - singletonObjects:单例对象的cache 63 | 64 | 在创建bean的时候,首先想到的是从cache中获取这个单例的bean,这个缓存就是singletonObjects。如果获取不到,并且对象正在创建中,就再从二级缓存earlySingletonObjects中获取。如果还是获取不到且允许singletonFactories通过getObject()获取,就从三级缓存singletonFactory.getObject()(三级缓存)获取,如果获取到了则:从singletonFactories中移除,并放入earlySingletonObjects中。其实也就是从三级缓存移动到了二级缓存。 65 | 66 | 从上面三级缓存的分析,我们可以知道,Spring解决循环依赖的诀窍就在于singletonFactories这个三级cache。这个cache的类型是ObjectFactory。这里就是解决循环依赖的关键,发生在createBeanInstance之后,也就是说单例对象此时已经被创建出来(调用了构造器)。这个对象已经被生产出来了,虽然还不完美(还没有进行初始化的第二步和第三步),但是已经能被人认出来了(根据对象引用能定位到堆中的对象),所以Spring此时将这个对象提前曝光出来让大家认识,让大家使用。 67 | 68 | 这样做有什么好处呢?让我们来分析一下“A的某个field或者setter依赖了B的实例对象,同时B的某个field或者setter依赖了A的实例对象”这种循环依赖的情况。A首先完成了初始化的第一步,并且将自己提前曝光到singletonFactories中,此时进行初始化的第二步,发现自己依赖对象B,此时就尝试去get(B),发现B还没有被create,所以走create流程,B在初始化第一步的时候发现自己依赖了对象A,于是尝试get(A),尝试一级缓存singletonObjects(肯定没有,因为A还没初始化完全),尝试二级缓存earlySingletonObjects(也没有),尝试三级缓存singletonFactories,由于A通过ObjectFactory将自己提前曝光了,所以B能够通过ObjectFactory.getObject拿到A对象(虽然A还没有初始化完全,但是总比没有好呀),B拿到A对象后顺利完成了初始化阶段1、2、3,完全初始化之后将自己放入到一级缓存singletonObjects中。此时返回A中,A此时能拿到B的对象顺利完成自己的初始化阶段2、3,最终A也完成了初始化,进去了一级缓存singletonObjects中,而且更加幸运的是,由于B拿到了A的对象引用,所以B现在hold住的A对象完成了初始化。 69 | 70 | 知道了这个原理时候,肯定就知道为啥Spring不能解决“A的构造方法中依赖了B的实例对象,同时B的构造方法中依赖了A的实例对象”这类问题了!**因为加入singletonFactories三级缓存的前提是执行了构造器,所以构造器的循环依赖没法解决。** 71 | 72 | -------------------------------------------------------------------------------- /Spring/assets/1550488358174.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550488358174.png -------------------------------------------------------------------------------- /Spring/assets/1550488375749.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550488375749.png -------------------------------------------------------------------------------- /Spring/assets/1550581880971.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550581880971.png -------------------------------------------------------------------------------- /Spring/assets/1550581966935.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550581966935.png -------------------------------------------------------------------------------- /Spring/assets/1550733141548.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550733141548.png -------------------------------------------------------------------------------- /Spring/assets/1550733552430.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550733552430.png -------------------------------------------------------------------------------- /Spring/assets/1550734532649.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550734532649.png -------------------------------------------------------------------------------- /Spring/assets/1550734606220.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550734606220.png -------------------------------------------------------------------------------- /Spring/assets/1550735364108.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550735364108.png -------------------------------------------------------------------------------- /Spring/assets/1550738778890.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550738778890.png -------------------------------------------------------------------------------- /Spring/assets/1550994028985.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550994028985.png -------------------------------------------------------------------------------- /Spring/assets/1550994192470.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550994192470.png -------------------------------------------------------------------------------- /Spring/assets/1550994395358.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1550994395358.png -------------------------------------------------------------------------------- /Spring/assets/1551191608732.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1551191608732.png -------------------------------------------------------------------------------- /Spring/assets/1551592963527.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1551592963527.png -------------------------------------------------------------------------------- /Spring/assets/1557750040106.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1557750040106.png -------------------------------------------------------------------------------- /Spring/assets/1557750800454.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1557750800454.png -------------------------------------------------------------------------------- /Spring/assets/1564648587419.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1564648587419.png -------------------------------------------------------------------------------- /Spring/assets/1564650051415.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1564650051415.png -------------------------------------------------------------------------------- /Spring/assets/1564650152116.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/Spring/assets/1564650152116.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556789923645.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556789923645.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556790038353.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556790038353.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556796082989.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556796082989.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556804669001.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556804669001.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556806242329.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556806242329.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556806882017.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556806882017.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556807205726.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556807205726.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809179729.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809179729.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809213048.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809213048.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809282699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809282699.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809408300.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809408300.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809827948.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809827948.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556809947047.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556809947047.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556810239953.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556810239953.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556810363718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556810363718.png -------------------------------------------------------------------------------- /SpringBoot/assets/1556810437699.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1556810437699.png -------------------------------------------------------------------------------- /SpringBoot/assets/1557136223672.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1557136223672.png -------------------------------------------------------------------------------- /SpringBoot/assets/1557145511355.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1557145511355.png -------------------------------------------------------------------------------- /SpringBoot/assets/1557149435665.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringBoot/assets/1557149435665.png -------------------------------------------------------------------------------- /SpringCloud/SpringCloud.md: -------------------------------------------------------------------------------- 1 | # 一、Eureka:注册中心 2 | 3 | ## 1.1 Eureka基本架构 4 | 5 | Eureka的作用:负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。 6 | 7 | 同时,服务提供方与Eureka之间通过`“心跳”`机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。 8 | 9 | 这就实现了服务的自动注册、发现、状态监控。 10 | 11 | ![](http://mycsdnblog.work/201919191705-9.png) 12 | 13 | - Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址 14 | - 提供者:启动后向Eureka注册自己信息(地址,提供什么服务) 15 | - 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新 16 | - 心跳(续约):提供者定期通过**http方式向**Eureka刷新自己的状态 17 | 18 | ## 1.2 Eureka-Server接收注册 19 | 20 | 正常情况下会进入 `PeerAwareInstanceRegistryImpl#register(...)` 方法: 21 | 22 | ### 1.2.1 注册表的真正结构 23 | 24 | ```java 25 | private final ConcurrentHashMap>> registry = new ConcurrentHashMap(); 26 | ``` 27 | 28 | 它就是一个ConcurrentHashMap, 其Key为应用的AppID,Value为一个Map,其中的键值对为该应用的各个实例。(InstanceId为键, `Lease>` 为值) 29 | 30 | ### 1.2.2 核心注册过程 31 | 32 | - **Eureka Server:**注册中心,里面有一个注册表,保存了各个服务所在的机器和端口号 33 | 34 | @EnableEurekaServer 35 | 36 | - **Eureka** **Client:**负责将这个服务的信息注册到Eureka Server中 37 | 38 | @EnableDiscoveryClient 39 | 40 | # 二、Zuul:服务网关 41 | 42 | # 三、Ribbon:负载均衡 43 | 44 | # 四、Feign:服务调用 45 | 46 | # 五、Hystix:熔断器 -------------------------------------------------------------------------------- /SpringMVC/assets/1550848187317.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringMVC/assets/1550848187317.png -------------------------------------------------------------------------------- /SpringMVC/assets/1550848309783.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringMVC/assets/1550848309783.png -------------------------------------------------------------------------------- /SpringMVC/assets/1550917918683.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringMVC/assets/1550917918683.png -------------------------------------------------------------------------------- /SpringMVC/assets/1550917982183.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/SpringMVC/assets/1550917982183.png -------------------------------------------------------------------------------- /java基础 (1).xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/java基础 (1).xmind -------------------------------------------------------------------------------- /分布式/一致性哈希.md: -------------------------------------------------------------------------------- 1 | 比如:一个分布式存储系统,要将数据存储到具体的节点(服务器)上, 在服务器数量不发生改变的情况下,如果采用普通的hash再对服务器总数量取模的方法(如key%服务器总数量),如果期间有服务器宕机了或者需要增加服务器,问题就出来了。 同一个key经过hash之后,再与服务器总数量取模的结果跟之前的结果会不一样,这就导致了之前保存数据的丢失。因此,引入了一致性Hash(Consistent Hashing)分布算法 2 | 3 | ![](http://mycsdnblog.work/201919091619-e.png) 4 | 5 | 把数据用hash函数(如md5,sha1),映射到一个圆环上,如上图所示,数据在存储时,先根据hash算法算出key的hash值,对应到这个环中的位置,如k1对应图中所示的位置同,然后沿着顺时针方向找到服务器节点B,然后把k1在存到B这个节点中。 6 | 7 | 如果B节点宕机了,则B上的数据就会落到C节点上,如下图所示: 8 | 9 | ![](http://mycsdnblog.work/201919091623-Q.png) 10 | 11 | 这样,只会影响C节点,对于其他节点A、D的数据不会造成影响。但是问题来了,这样会造成C节点负载过重的情况,因为C节点承担了B节点的数据,所以C节点容易宕机,这样造成了分布不均匀。 12 | 13 | 为了解决这个问题,引入了“虚拟节点“的概念:即想象空上环上有很多”虚拟节点“,一个真实的服务器节点对应多个虚拟节点,数据存储的时候沿着环的顺时针方向找到虚拟节点,就找到了对应的真实服务器节点。如下图: 14 | 15 | ![](http://mycsdnblog.work/201919091624-l.png) 16 | 17 | 图中的A1、A2、B1、B2、C1、C2、D1、D2都是虚拟节点,机器A负载存储A1、A2的数据,机器B负载存储B1、B2的数据,机器C负载存储C1、C2的数据。由于这些虚拟节点数量很多,均匀分布,因此不会造成“雪崩”现象。 18 | 19 | -------------------------------------------------------------------------------- /分布式/分布式.md: -------------------------------------------------------------------------------- 1 | # 一、分布式事务 2 | 3 | # 二、分布式生成唯一ID 4 | 5 | -------------------------------------------------------------------------------- /分布式/分布式锁.md: -------------------------------------------------------------------------------- 1 | # 一、什么是分布式锁 2 | 3 | 分布式锁其实可以理解为:控制**分布式系统**有序的去对**共享资源进行操作**,**通过互斥来保持一致性**。 4 | 5 | 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁就是保证这个房子只有一个门并且一次只有一个人可以进,而且门只有一把钥匙。然后许多人要去看书,可以,排队,第一个人拿着钥匙把门打开进屋看书并且把门锁上,然后第二个人没有钥匙,那就等着,等第一个出来,然后你在拿着钥匙进去,然后就是以此类推。 6 | 7 | # 二、实现原理 8 | 9 | - 互斥性 10 | 11 | - - 保证同一时间只有一个客户端可以拿到锁,也就是可以对共享资源进行操作 12 | 13 | - 安全性 14 | 15 | - - 只有加锁的服务才能有解锁权限,也就是不能让a加的锁,bcd都可以解锁,如果都能解锁那分布式锁就没啥意义了 16 | - 可能出现的情况就是a去查询发现持有锁,就在准备解锁,这时候忽然a持有的锁过期了,然后b去获得锁,因为a锁过期,b拿到锁,这时候a继续执行第二步进行解锁如果不加校验,就将b持有的锁就给删除了 17 | 18 | - 避免死锁 19 | 20 | - - 出现死锁就会导致后续的任何服务都拿不到锁,不能再对共享资源进行任何操作了 21 | 22 | - 保证加锁与解锁操作是原子性操作 23 | 24 | - - 这个其实属于是实现分布式锁的问题,假设a用redis实现分布式锁 25 | - 假设加锁操作,操作步骤分为两步: 26 | - 1,设置key set(key,value)2,给key设置过期时间 27 | 28 | - - 假设现在a刚实现set后,程序崩了就导致了没给key设置过期时间就导致key一直存在就发生了死锁 29 | 30 | # 三、使用Redis实现分布式锁 31 | 32 | 首先,为了确保分布式锁可用,我们至少要确保锁的实现同时满足以下四个条件: 33 | 34 | - **互斥性。在任意时刻,只有一个客户端能持有锁。** 35 | - **不会发生死锁。即使有一个客户端在持有锁的期间崩溃而没有主动解锁,也能保证后续其他客户端能加锁。** 36 | - **具有容错性。只要大部分的Redis节点正常运行,客户端就可以加锁和解锁。** 37 | - **解铃还须系铃人。加锁和解锁必须是同一个客户端,客户端自己不能把别人加的锁给解了。** 38 | 39 | 可以看到,我们加锁就一行代码:**jedis.set(String key, String value, String nxxx, String expx, int time)**,这个set()方法一共有五个形参: 40 | 41 | - 第一个为key,我们使用key来当锁,因为key是唯一的。 42 | - 第二个为value,我们传的是requestId,很多童鞋可能不明白,有key作为锁不就够了吗,为什么还要用到value?原因就是我们在上面讲到可靠性时,分布式锁要满足第四个条件**解铃还须系铃人**,通过给value赋值为requestId,我们就知道这把锁是哪个请求加的了,在解锁的时候就可以有依据。requestId可以使用`UUID.randomUUID().toString()`方法生成。 43 | - 第三个为nxxx,这个参数我们填的是NX,意思是SET IF NOT EXIST,即当key不存在时,我们进行set操作;若key已经存在,则不做任何操作; 44 | - 第四个为expx,这个参数我们传的是PX,意思是我们要给这个key加一个过期的设置,具体时间由第五个参数决定。 45 | - 第五个为time,与第四个参数相呼应,代表key的过期时间。 46 | 47 | 总的来说,执行上面的set()方法就只会导致两种结果:1. 当前没有锁(key不存在),那么就进行加锁操作,并对锁设置个有效期,同时value表示加锁的客户端。2. 已有锁存在,不做任何操作。 48 | 49 | 心细的童鞋就会发现了,我们的加锁代码满足我们**可靠性**里描述的三个条件。**首先,set()加入了NX参数,可以保证如果已有key存在,则函数不会调用成功,也就是只有一个客户端能持有锁,满足互斥性。其次,由于我们对锁设置了过期时间,即使锁的持有者后续发生崩溃而没有解锁,锁也会因为到了过期时间而自动解锁(即key被删除),不会发生死锁。最后,因为我们将value赋值为requestId,代表加锁的客户端请求标识,那么在客户端在解锁的时候就可以进行校验是否是同一个客户端。由于我们只考虑Redis单机部署的场景,所以容错性我们暂不考虑。** 50 | 51 | -------------------------------------------------------------------------------- /刷题/Programmer Code Interview Guide.md: -------------------------------------------------------------------------------- 1 | # 一、在行列都排好序的矩阵中找指定的数 2 | 3 | ```java 4 | package com.example.problem1; 5 | 6 | import java.util.Scanner; 7 | 8 | /** 9 | * @Author: 98050 10 | * @Time: 2019-08-02 15:22 11 | * @Feature: 12 | */ 13 | public class Main { 14 | 15 | public static void main(String[] args) { 16 | Scanner sc = new Scanner(System.in); 17 | int N = sc.nextInt(); 18 | int M = sc.nextInt(); 19 | int K = sc.nextInt(); 20 | 21 | int[][] nums = new int[N][M]; 22 | for (int i = 0; i < N; i++) { 23 | for (int j = 0; j < M; j++) { 24 | nums[i][j] = sc.nextInt(); 25 | } 26 | } 27 | 28 | int i = N - 1; 29 | int j = 0; 30 | boolean tag = false; 31 | while (i >= 0 && j < M){ 32 | if (nums[i][j] == K){ 33 | tag = true; 34 | break; 35 | }else if (nums[i][j] > K){ 36 | i--; 37 | }else { 38 | j++; 39 | } 40 | } 41 | if (tag){ 42 | System.out.println("Yes"); 43 | }else { 44 | System.out.println("No"); 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | # 二、最长的可整合子数组长度 51 | 52 | ```java 53 | package com.example.problem2; 54 | 55 | import java.io.Serializable; 56 | import java.util.*; 57 | 58 | /** 59 | * @Author: 98050 60 | * @Time: 2019-08-02 15:35 61 | * @Feature: 62 | */ 63 | public class Main { 64 | 65 | public static void main(String[] args) { 66 | Scanner sc = new Scanner(System.in); 67 | int length = sc.nextInt(); 68 | Set set = new TreeSet(); 69 | for (int i = 0; i < length; i++) { 70 | set.add(sc.nextInt()); 71 | } 72 | Integer[] nums = new Integer[set.size()]; 73 | set.toArray(nums); 74 | int result = 0; 75 | int len = 1; 76 | int pre = nums[0]; 77 | 78 | for (int i = 1; i < nums.length; i++) { 79 | if (nums[i] - 1 == pre){ 80 | len++; 81 | }else { 82 | len = 0; 83 | } 84 | result = Math.max(result, len); 85 | pre = nums[i]; 86 | } 87 | System.out.println(result); 88 | } 89 | } 90 | ``` 91 | 92 | -------------------------------------------------------------------------------- /刷题/assets/1561196630964.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/刷题/assets/1561196630964.png -------------------------------------------------------------------------------- /刷题/leetcode-markdown/HashMap.md: -------------------------------------------------------------------------------- 1 | [1、LeetCode 299 猜数字游戏](https://leetcode-cn.com/problems/bulls-and-cows/submissions/) 2 | 3 | 思路:先遍历一次secret,找到guess和secret位置相同数字相同的进行统计,并且使用HashMap记录不相同数字的出现次数。然后再遍历guess,排除相同位置的数字,然后统计不同位置的相同数字的出现次数。 4 | 5 | ```java 6 | class Solution { 7 | public String getHint(String secret, String guess) { 8 | int A = 0, B = 0; 9 | StringBuilder sb = new StringBuilder(); 10 | HashMap map = new HashMap<>(); 11 | for (int i = 0; i < secret.length(); i++) { 12 | if (secret.charAt(i) == guess.charAt(i)){ 13 | A++; 14 | }else { 15 | map.put(secret.charAt(i), map.getOrDefault(secret.charAt(i),0) + 1); 16 | } 17 | } 18 | for (int i = 0; i < guess.length(); i++) { 19 | if (map.containsKey(guess.charAt(i)) && secret.charAt(i) != guess.charAt(i)){ 20 | if (map.get(guess.charAt(i)) > 0) { 21 | map.put(guess.charAt(i), map.get(guess.charAt(i)) - 1); 22 | B++; 23 | } 24 | } 25 | } 26 | return sb.append(A).append("A").append(B).append("B").toString(); 27 | } 28 | } 29 | ``` 30 | 31 | 简洁版: 32 | 33 | ```java 34 | class Solution { 35 | public String getHint(String secret, String guess) { 36 | int[] nums = new int[10]; 37 | int A = 0,B = 0; 38 | for (int i = 0; i < secret.length(); i++) { 39 | if (secret.charAt(i) == guess.charAt(i)){ 40 | A++; 41 | }else { 42 | nums[secret.charAt(i) - '0']++; 43 | } 44 | } 45 | for (int i = 0; i < guess.length(); i++) { 46 | if (nums[guess.charAt(i) - '0'] > 0 && secret.charAt(i) != guess.charAt(i)){ 47 | nums[guess.charAt(i) - '0']--; 48 | B++; 49 | } 50 | } 51 | return A + "A" + B + "B"; 52 | } 53 | } 54 | ``` 55 | 56 | 2、[LeetCode 676 实现一个魔法字典](https://leetcode-cn.com/problems/implement-magic-dictionary/) 57 | 58 | **如果一个单词中只有一个字符可以更改以使字符串相等,那么两个单词就是邻居。** 59 | 60 | 思路:首先针对字典中的每个单词,构造其所有的邻居,并且使用map存储每个邻居出现的次数,然后将所有单词放入set中。当进行搜索时,先构造搜索单词word所对应的邻居,然后从map中进行查询,当前构造的邻居为sb,如果`map.get(sb)>1 || map.get(sb)==1&&!set.contains(word)`返回`true` 61 | 62 | 当map.get(sb)>1,说明字典中存在两个以上的单词,它们只有一个位置上的字符不相同。下面列出几种情况: 63 | 64 | dict:["hello","hallo"] search:["hello"],["hhllo"] 返回两个true 65 | 66 | dict:["hello"] search:["hello"] 返回false 67 | 68 | dict:["hello"] search:["hallo"] 返回true 69 | 70 | ```java 71 | class MagicDictionary { 72 | 73 | HashMap map; 74 | Set set; 75 | /** Initialize your data structure here. */ 76 | public MagicDictionary() { 77 | map = new HashMap<>(); 78 | set = new HashSet<>(); 79 | } 80 | 81 | /** Build a dictionary through a list of words */ 82 | public void buildDict(String[] dict) { 83 | for (String s : dict){ 84 | for (int i = 0; i < s.length(); i++) { 85 | StringBuilder sb = new StringBuilder(s); 86 | sb.setCharAt(i,'*'); 87 | map.put(sb.toString(),map.getOrDefault(sb.toString(),0) + 1); 88 | } 89 | set.add(s); 90 | } 91 | } 92 | 93 | /** Returns if there is any word in the trie that equals to the given word after modifying exactly one character */ 94 | public boolean search(String word) { 95 | for (int i = 0; i < word.length(); i++) { 96 | StringBuilder sb = new StringBuilder(word); 97 | sb.setCharAt(i,'*'); 98 | int c = map.getOrDefault(sb.toString(),0); 99 | if (c > 1 || c == 1 && !set.contains(word)){ 100 | return true; 101 | } 102 | } 103 | return false; 104 | } 105 | } 106 | 107 | /** 108 | * Your MagicDictionary object will be instantiated and called as such: 109 | * MagicDictionary obj = new MagicDictionary(); 110 | * obj.buildDict(dict); 111 | * boolean param_2 = obj.search(word); 112 | */ 113 | ``` 114 | -------------------------------------------------------------------------------- /刷题/动态规划/(120)三角形最小路径和.md: -------------------------------------------------------------------------------- 1 | Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below. 2 | 3 | For example, given the following triangle 4 | 5 | ``` 6 | [ 7 | [2], 8 | [3,4], 9 | [6,5,7], 10 | [4,1,8,3] 11 | ] 12 | ``` 13 | 14 | The minimum path sum from top to bottom is `11` (i.e., **2** + **3** + **5** + **1** = 11). 15 | 16 | **Note:** 17 | 18 | Bonus point if you are able to do this using only *O*(*n*) extra space, where *n* is the total number of rows in the triangle. 19 | 20 | 思路一:动态规划,从上往下遍历 21 | 22 | 当前位置(i,j)的路径长度为: 23 | $$ 24 | dp[i][j] = triangle.get(i - 1).get(j - 1) + min(dp[i - 1][j - 1],dp[i - 1][j]); 25 | $$ 26 | 然后遍历最后一行找到最小值即可,空间复杂度O(n^2) 27 | 28 | ```java 29 | package com.problem120; 30 | 31 | import java.util.ArrayList; 32 | import java.util.Arrays; 33 | import java.util.List; 34 | 35 | class Solution { 36 | 37 | public int minimumTotal(List> triangle) { 38 | int row = triangle.size(); 39 | if (row == 0){ 40 | return 0; 41 | } 42 | int col = triangle.get(row - 1).size(); 43 | int[][] dp = new int[row + 1][col + 1]; 44 | int res = Integer.MAX_VALUE; 45 | dp[1][1] = triangle.get(0).get(0); 46 | 47 | for (int i = 2; i < row + 1; i++) { 48 | for (int j = 1; j < triangle.get(i - 1).size() + 1; j++) { 49 | 50 | int a = j - 1 == 0? Integer.MAX_VALUE : dp[i - 1][j - 1]; 51 | int b = j == triangle.get(i - 1).size() ? Integer.MAX_VALUE : dp[i - 1][j]; 52 | dp[i][j] = triangle.get(i - 1).get(j - 1) + Math.min(a,b); 53 | } 54 | } 55 | for (int i = 1; i < col + 1; i++) { 56 | res = Math.min(res, dp[row][i]); 57 | } 58 | return res; 59 | } 60 | } 61 | ``` 62 | 63 | 思路二:空间复杂度O(n),从下往上遍历,从最后一行开始,向上计算。状态转移方程如下: 64 | $$ 65 | dp[j] = Math.min(dp[j],dp[j + 1]) + triangle.get(i).get(j); 66 | $$ 67 | 68 | ```java 69 | package com.problem120; 70 | 71 | import java.util.List; 72 | 73 | /** 74 | * @Author: 98050 75 | * @Time: 2019-10-29 13:07 76 | * @Feature: 77 | */ 78 | public class Solution2 { 79 | 80 | public int minimumTotal(List> triangle) { 81 | int row = triangle.size(); 82 | if (row == 0){ 83 | return 0; 84 | } 85 | int col = triangle.get(row - 1).size(); 86 | int[] dp = new int[col + 1]; 87 | for (int i = row - 1; i >= 0; i--) { 88 | for (int j = 0; j < triangle.get(i).size(); j++) { 89 | dp[j] = Math.min(dp[j],dp[j + 1]) + triangle.get(i).get(j); 90 | } 91 | } 92 | return dp[0]; 93 | } 94 | } 95 | ``` 96 | 97 | -------------------------------------------------------------------------------- /刷题/动态规划/(221)最大正方形.md: -------------------------------------------------------------------------------- 1 | Given a 2D binary matrix filled with 0's and 1's, find the largest square containing only 1's and return its area. 2 | 3 | **Example:** 4 | 5 | ``` 6 | Input: 7 | 8 | 1 0 1 0 0 9 | 1 0 1 1 1 10 | 1 1 1 1 1 11 | 1 0 0 1 0 12 | 13 | Output: 4 14 | ``` 15 | 16 | 思路:找到正方形的边长,然后计算其面积。用一个dp数组来记录当前位置的最大正方形边长。 17 | 18 | 如果当前位置(i,j)为‘1’,那么就更新`dp[i][j]`的值为: 19 | $$ 20 | min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1 21 | $$ 22 | 找到当前位置(i,j)所能构成的最大正方形边长,然后再计算正方形的面积,取最大值即可。 23 | 24 | ![](http://mycsdnblog.work/201919281103-5.png) 25 | 26 | ```java 27 | package com.problem221; 28 | 29 | /** 30 | * @Author: 98050 31 | * @Time: 2019-10-28 09:59 32 | * @Feature: 33 | */ 34 | public class Solution { 35 | 36 | public int maximalSquare(char[][] matrix) { 37 | int row = matrix.length; 38 | if (row == 0){ 39 | return 0; 40 | } 41 | int col = matrix[0].length; 42 | int[][] dp = new int[row + 1][col + 1]; 43 | int res = 0; 44 | for (int i = 1; i < row + 1; i++) { 45 | for (int j = 1; j < col + 1; j++) { 46 | if (matrix[i - 1][j - 1] == '1'){ 47 | dp[i][j] = Math.min(dp[i - 1][j],Math.min(dp[i][j - 1],dp[i - 1][j - 1])) + 1; 48 | res = Math.max(res, dp[i][j] * dp[i][j]); 49 | } 50 | } 51 | } 52 | return res; 53 | } 54 | } 55 | ``` 56 | 57 | -------------------------------------------------------------------------------- /刷题/动态规划/(84)柱状图中最大的矩形.md: -------------------------------------------------------------------------------- 1 | Given *n* non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram. 2 | 3 | 4 | 5 | ![img](https://assets.leetcode.com/uploads/2018/10/12/histogram.png) 6 | Above is a histogram where width of each bar is 1, given height = `[2,1,5,6,2,3]`. 7 | 8 | 9 | 10 | ![img](https://assets.leetcode.com/uploads/2018/10/12/histogram_area.png) 11 | The largest rectangle is shown in the shaded area, which has area = `10` unit. 12 | 13 | 14 | 15 | **Example:** 16 | 17 | ``` 18 | Input: [2,1,5,6,2,3] 19 | Output: 10 20 | ``` 21 | 22 | 方法一:暴力 23 | 24 | 以当前柱状图为高,寻找矩形的宽度,然后计算面积 25 | 26 | ```java 27 | package com.problem84; 28 | 29 | class Solution { 30 | public int largestRectangleArea(int[] heights) { 31 | int res = 0; 32 | 33 | for (int i = 0; i < heights.length; i++) { 34 | int count = 1; 35 | for (int j = i - 1; j >= 0; j--) { 36 | if (heights[j] >= heights[i]){ 37 | count++; 38 | }else { 39 | break; 40 | } 41 | } 42 | for (int j = i + 1; j < heights.length; j++) { 43 | if (heights[j] >= heights[i]){ 44 | count++; 45 | }else { 46 | break; 47 | } 48 | } 49 | res = Math.max(res, count * heights[i]); 50 | } 51 | return res; 52 | } 53 | } 54 | ``` 55 | 56 | 方法二:分治 57 | 58 | 通过观察,可以发现,最大面积矩形存在于以下几种情况: 59 | 60 | - 确定了最矮柱子以后,矩形的宽尽可能往两边延伸。 61 | 62 | - 在最矮柱子左边的最大面积矩形(子问题)。 63 | 64 | - 在最矮柱子右边的最大面积矩形(子问题)。 65 | 66 | 67 | ```java 68 | package com.problem84; 69 | 70 | /** 71 | * @Author: 98050 72 | * @Time: 2019-10-28 11:51 73 | * @Feature: 74 | */ 75 | public class Solution2 { 76 | 77 | public int largestRectangleArea(int[] heights) { 78 | return find(heights,0,heights.length - 1); 79 | } 80 | 81 | private int find(int[] heights, int low, int high) { 82 | if (low > high){ 83 | return 0; 84 | } 85 | int index = low; 86 | for (int i = low; i <= high; i++) { 87 | if (heights[i] < heights[index]){ 88 | index = i; 89 | } 90 | } 91 | return Math.max(heights[index] * (high - low + 1),Math.max(find(heights,low,index - 1),find(heights, index + 1, high))); 92 | } 93 | } 94 | ``` 95 | 96 | -------------------------------------------------------------------------------- /刷题/动态规划/(85)最大矩形.md: -------------------------------------------------------------------------------- 1 | Given a 2D binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area. 2 | 3 | **Example:** 4 | 5 | ``` 6 | Input: 7 | [ 8 | ["1","0","1","0","0"], 9 | ["1","0","1","1","1"], 10 | ["1","1","1","1","1"], 11 | ["1","0","0","1","0"] 12 | ] 13 | Output: 6 14 | ``` 15 | 16 | 根据84题来解决,计算每一行矩形的高度,然后在柱状图中找最大矩形。 17 | 18 | ```java 19 | package com.problem85; 20 | 21 | class Solution { 22 | public int maximalRectangle(char[][] matrix) { 23 | int row = matrix.length; 24 | if (row == 0){ 25 | return 0; 26 | } 27 | int col = matrix[0].length; 28 | int res = 0; 29 | int[] heights = new int[col]; 30 | for (int i = 0; i < row; i++) { 31 | for (int j = 0; j < col; j++) { 32 | if (matrix[i][j] == '1') { 33 | heights[j] += 1; 34 | }else { 35 | heights[j] = 0; 36 | } 37 | } 38 | res = Math.max(res, largestRectangleArea(heights)); 39 | } 40 | return res; 41 | } 42 | 43 | public int largestRectangleArea(int[] heights) { 44 | return find(heights,0,heights.length - 1); 45 | } 46 | 47 | private int find(int[] heights, int low, int high) { 48 | if (low > high){ 49 | return 0; 50 | } 51 | int index = low; 52 | for (int i = low; i <= high; i++) { 53 | if (heights[i] < heights[index]){ 54 | index = i; 55 | } 56 | } 57 | return Math.max(heights[index] * (high - low + 1),Math.max(find(heights,low,index - 1),find(heights, index + 1, high))); 58 | } 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /前端/前端.md: -------------------------------------------------------------------------------- 1 | # 一、RestFul的优点 2 | 3 | 1. 轻量,直接基于http,不再需要任何别的诸如消息协议。get/post/put/delete为CRUD操作 4 | 5 | 2. 面向资源,一目了然,具有自解释性。 6 | 7 | 3. 数据描述简单,一般以xml,json做数据交换。 8 | 9 | 4. 无状态,在调用一个接口(访问、操作资源)的时候,可以不用考虑上下文,不用考虑当前状态,极大的降低了复杂度。 10 | 11 | 5. 简单、低耦合 12 | 13 | # 二、VUE的生命周期 14 | 15 | ![](http://mycsdnblog.work/201919241738-U.png) 16 | 17 | # 三、Nuxt.js 18 | 19 | # 四、Promise异步调用 20 | 21 | # 五、async/await方法同步调用 22 | 23 | -------------------------------------------------------------------------------- /原理/assets/1555075439248.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/原理/assets/1555075439248.png -------------------------------------------------------------------------------- /原理/assets/1555076016953.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/原理/assets/1555076016953.png -------------------------------------------------------------------------------- /原理/学习大纲.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/原理/学习大纲.jpg -------------------------------------------------------------------------------- /场景题/场景题.md: -------------------------------------------------------------------------------- 1 | # 1、给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 2 | 3 | 看到问题的想法是采用bitmap:1个字节可以表示8个整数是否出现的情况(出现则对应的位置1,否则为0),那么表示40亿个整数的情况需要40亿/8=5亿,约500M的空间.空间复杂度是O(n)+O(1); 4 | 5 | 还有更好的方法: 6 | 这个问题在《编程珠玑》里有很好的描述,大家可以参考下面的思路,探讨一下: 7 | 又因为2^32为40亿多,所以给定一个数可能在,也可能不在其中; 8 | **这里我们把40亿个数中的每一个用32位的二进制来表示** 9 | 10 | 假设这40亿个数开始放在一个文件中。 11 | 12 | 然后将这40亿个数分成两类: 13 | 1.最高位为0 14 | 2.最高位为1 15 | 并将这两类分别写入到两个文件中,其中一个文件中数的个数<=20亿,而另一个>=20亿(这相当于折半了); 16 | 与要查找的数的最高位比较并接着进入相应的文件再查找 17 | 18 | 再然后把这个文件为又分成两类: 19 | 1.次最高位为0 20 | 2.次最高位为1 21 | 22 | 并将这两类分别写入到两个文件中,其中一个文件中数的个数<=10亿,而另一个>=10亿(这相当于折半了); 23 | 与要查找的数的次最高位比较并接着进入相应的文件再查找。 24 | ....... 25 | 以此类推,就可以找到了,而且时间复杂度为O(logn) 26 | # 2、根据一段日志结构计算出在线人数 27 | 28 | 有如下一段日志: 29 | 30 | ```js 31 | var log = [ 32 | { 33 | user: 1, 34 | status: 'enter', 35 | time: 1545622430621 36 | }, 37 | { 38 | user: 2, 39 | status: 'leave', 40 | time: 1545622437881 41 | }, 42 | { 43 | user: 3, 44 | status: 'enter', 45 | time: 1545622430621 46 | } 47 | ] 48 | ``` 49 | 50 | 字段说明: 51 | 52 | - `user`: 用户id; 53 | - `status`: 状态,`enter`表示用户进入直播间,`leave`表示用户离开直播间; 54 | - `time`: 该条记录发生的时间戳。 55 | 56 | 其实这里的`user`用户id在该题目下可以忽略掉,很容易误导我们。 57 | 58 | 题目要求我们计算出在线人数最多的那个时间点,所以我们第一步就是要知道所有时间点上的在线人数。 59 | 60 | 大概思路:先计算出所有时间点上的在线人数,然后在比较出人数最多的那个时间点。 61 | 62 | **计算每个时间点的用户人数** 63 | 64 | 这里我们以秒为单位,也就是计算每秒的当前在线人数。 65 | 66 | ```js 67 | // 我们初始化了一个长度等于86400的timeList数组,也就是一天的秒数,因为我们需要计算当前秒的在线人数。 68 | var timeList = new Array(60 * 60 *24); 69 | var onlineList = []; 70 | log.forEach((item) => { 71 | const hours = time.getHours(); // 获取小时 72 | const min = time.getMinutes(); // 获取分钟 73 | const seconds = time.getSeconds(); // 获取秒 74 | const currentSecond = 60 * 60 * hours + 60 * min + seconds; // 这样可以得到该时间点的时间位于当天的第几秒 75 | 76 | let count = onlineList[currentSecond] || 0; 77 | if (item.type === 'enter') { 78 | // 进入 +1 79 | count++; 80 | } else { 81 | // 离开 82 | count--; 83 | } 84 | onlineList[currentSecond] = count; 85 | 86 | }); 87 | 1s: onlineList[0] = timeList[0]; 88 | 2s: onlineList[1] = onlineList[1] + timeList[2]; 89 | 3s: onlineList[2] = onlineList[2] + timeList[3]; 90 | ns: onlineList[n] = onelineList[n-2]+timeList[n]; 91 | .... 92 | ``` 93 | 94 | 总体思路就是,先计算出整个时间点(秒)的人数变化,然后加上前一秒的人数就可以得到当前的人数,这样就得到了每一秒的在线人数,其中要注意的是,每一秒的在线人数需要从索引0位置开始,去循环遍历的计算出每一秒的人数。 95 | 96 | 这样我们就得到了每个时间点(秒)的在线人数,然后我们可以通过一些简单的排序方法,如冒泡排序,拿到在线人数最大的那个时间点。 97 | 98 | ------ 99 | 100 | 如果求最大在线人数的区间,那么就可以按照求数组的最大子序和来 101 | 102 | -------------------------------------------------------------------------------- /场景题/海量数据查询.md: -------------------------------------------------------------------------------- 1 | # 给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中? 2 | 3 | 看到问题的想法是采用bitmap:1个字节可以表示8个整数是否出现的情况(出现则对应的位置1,否则为0),那么表示40亿个整数的情况需要40亿/8=5亿,约500M的空间.空间复杂度是O(n)+O(1); 4 | 还有更好的方法: 5 | 这个问题在《编程珠玑》里有很好的描述,大家可以参考下面的思路,探讨一下: 6 | 又因为2^32为40亿多,所以给定一个数可能在,也可能不在其中; 7 | **这里我们把40亿个数中的每一个用32位的二进制来表示** 8 | 假设这40亿个数开始放在一个文件中。 9 | 10 | 然后将这40亿个数分成两类: 11 | 1.最高位为0 12 | 2.最高位为1 13 | 并将这两类分别写入到两个文件中,其中一个文件中数的个数<=20亿,而另一个>=20亿(这相当于折半了); 14 | 与要查找的数的最高位比较并接着进入相应的文件再查找 15 | 16 | 再然后把这个文件为又分成两类: 17 | 1.次最高位为0 18 | 2.次最高位为1 19 | 20 | 并将这两类分别写入到两个文件中,其中一个文件中数的个数<=10亿,而另一个>=10亿(这相当于折半了); 21 | 与要查找的数的次最高位比较并接着进入相应的文件再查找。 22 | ....... 23 | 以此类推,就可以找到了,而且时间复杂度为O(logn) 24 | 25 | -------------------------------------------------------------------------------- /大纲.md: -------------------------------------------------------------------------------- 1 | # 一、Java基础 2 | 3 | 1、List 和 Set 的区别 4 | 2、HashSet 是如何保证不重复的 5 | 3、HashMap 是线程安全的吗,为什么不是线程安全的(最好画图说明多线程环境下不安全)? 6 | 4、HashMap 的扩容过程 7 | 5、HashMap 1.7 与 1.8 的 区别,说明 1.8 做了哪些优化,如何优化的? 8 | 6、final finally finalize 9 | 7、强引用 、软引用、 弱引用、虚引用 10 | 8、Java反射 11 | 9、Arrays.sort 实现原理和 Collection 实现原理 12 | 10、LinkedHashMap的应用 13 | 11、cloneable接口实现原理 14 | 12、异常分类以及处理机制 15 | 13、wait和sleep的区别 16 | 14、数组在内存中如何分配 17 | 18 | # 二、Java并发 19 | 20 | 1、synchronized 的实现原理以及锁优化? 21 | 2、volatile 的实现原理? 22 | 3、Java 的信号灯? 23 | 4、synchronized 在静态方法和普通方法的区别? 24 | 5、怎么实现所有线程在等待某个事件的发生才会去执行? 25 | 6、CAS?CAS 有什么缺陷,如何解决? 26 | 7、synchronized 和 lock 有什么区别? 27 | 8、Hashtable 是怎么加锁的 ? 28 | 9、HashMap 的并发问题? 29 | 10、ConcurrenHashMap 介绍?1.8 中为什么要用红黑树? 30 | 11、AQS 31 | 12、如何检测死锁?怎么预防死锁? 32 | 13、Java 内存模型? 33 | 14、如何保证多线程下 i++ 结果正确? 34 | 15、线程池的种类,区别和使用场景? 35 | 16、分析线程池的实现原理和线程的调度过程? 36 | 17、线程池如何调优,最大数目如何确认? 37 | 18、ThreadLocal原理,用的时候需要注意什么? 38 | 19、CountDownLatch 和 CyclicBarrier 的用法,以及相互之间的差别? 39 | 20、LockSupport工具 40 | 21、Condition接口及其实现原理 41 | 22、Fork/Join框架的理解 42 | 23、分段锁的原理,锁力度减小的思考 43 | 24、八种阻塞队列以及各个阻塞队列的特性 44 | 45 | # 三、Spring 46 | 47 | 1、BeanFactory 和 FactoryBean? 48 | 2、Spring IOC 的理解,其初始化过程? 49 | 3、BeanFactory 和 ApplicationContext? 50 | 4、Spring Bean 的生命周期,如何被管理的? 51 | 5、Spring Bean 的加载过程是怎样的? 52 | 6、如果要你实现Spring AOP,请问怎么实现? 53 | 7、如果要你实现Spring IOC,你会注意哪些问题? 54 | 8、Spring 是如何管理事务的,事务管理机制? 55 | 9、Spring 的不同事务传播行为有哪些,干什么用的? 56 | 10、Spring 中用到了那些设计模式? 57 | 11、Spring MVC 的工作原理? 58 | 12、Spring 循环注入的原理? 59 | 13、Spring AOP的理解,各个术语,他们是怎么相互工作的? 60 | 14、Spring 如何保证 Controller 并发的安全? 61 | 62 | # 四、数据库 63 | 64 | 1、mysql分页有什么优化 65 | 2、悲观锁、乐观锁 66 | 3、组合索引,最左原则 67 | 4、mysql 的表锁、行锁 68 | 5、mysql 性能优化 69 | 6、mysql的索引分类:B+,hash;什么情况用什么索引 70 | 7、事务的特性和隔离级别 71 | 72 | # 五、缓存 73 | 74 | 1、Redis用过哪些数据数据,以及Redis底层怎么实现 75 | 2、Redis缓存穿透,缓存雪崩 76 | 3、如何使用Redis来实现分布式锁 77 | 4、Redis的并发竞争问题如何解决 78 | 5、Redis持久化的几种方式,优缺点是什么,怎么实现的 79 | 6、Redis的缓存失效策略 80 | 7、Redis集群,高可用,原理 81 | 8、Redis缓存分片 82 | 9、Redis的数据淘汰策略 83 | 84 | # 六、JVM 85 | 1、详细jvm内存模型 86 | 2、讲讲什么情况下回出现内存溢出,内存泄漏? 87 | 3、说说Java线程栈 88 | 4、JVM 年轻代到年老代的晋升过程的判断条件是什么呢? 89 | 5、JVM 出现 fullGC 很频繁,怎么去线上排查问题? 90 | 6、类加载为什么要使用双亲委派模式,有没有什么场景是打破了这个模式? 91 | 7、类的实例化顺序 92 | 8、JVM垃圾回收机制,何时触发MinorGC等操作 93 | 9、JVM 中一次完整的 GC 流程(从 ygc 到 fgc)是怎样的 94 | 10、各种回收器,各自优缺点,重点CMS、G1 95 | 11、各种回收算法 96 | 12、OOM错误,stackoverflow错误,permgen space错误 97 | 98 | # 七、分布式相关 99 | 100 | 1、Dubbo的底层实现原理和机制 101 | 2、描述一个服务从发布到被消费的详细过程 102 | 3、分布式系统怎么做服务治理 103 | 4、接口的幂等性的概念 104 | 5、消息中间件如何解决消息丢失问题 105 | 6、Dubbo的服务请求失败怎么处理 106 | 7、重连机制会不会造成错误 107 | 8、对分布式事务的理解 108 | 9、如何实现负载均衡,有哪些算法可以实现? 109 | 10、Zookeeper的用途,选举的原理是什么? 110 | 11、数据的垂直拆分水平拆分。 111 | 12、zookeeper原理和适用场景 112 | 13、zookeeper watch机制 113 | 14、redis 114 | 15、分布式集群下如何做到唯一序列号 115 | 16、如何做一个分布式锁 116 | 17、用过哪些MQ,怎么用的,和其他mq比较有什么优缺点,MQ的连接是线程安全的吗 117 | 18、MQ系统的数据如何保证不丢失 118 | 19、列举出你能想到的数据库分库分表策略;分库分表后,如何解决全表查询的问题 119 | 20、zookeeper的选举策略 120 | 21、全局ID -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——ArrayBlockingQueue.md: -------------------------------------------------------------------------------- 1 | 一、介绍 2 | 3 | 二、原理和数据结构 4 | 5 | 三、方法列表 6 | 7 | 四、源码分析 8 | 9 | 五、使用 -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——ConcurrentSkipListMap.md: -------------------------------------------------------------------------------- 1 | 一、介绍 2 | 3 | 二、原理和数据结构 4 | 5 | 三、方法列表 6 | 7 | 四、源码分析 8 | 9 | 五、使用 -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——ConcurrentSkipListSet.md: -------------------------------------------------------------------------------- 1 | 一、介绍 2 | 3 | 二、原理和数据结构 4 | 5 | 三、方法列表 6 | 7 | 四、源码分析 8 | 9 | 五、使用 -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——CopyOnWriteArraySet.md: -------------------------------------------------------------------------------- 1 | #### 一、介绍 2 | 3 | CopyOnWriteArraySet它是线程安全的无序的集合,可以将它理解成线程安全的HashSet。CopyOnWriteArraySet和HashSet虽然都继承于共同的父类AbstractSet,但是,HashSet是通过散列表(HashMap)实现的,而CopyOnWriteArraySet则是通过动态数组(CopyOnWriteArrayList)实现的,并不是散列表。 和CopyOnWriteArrayList类似,CopyOnWriteArraySet具有以下特性: 4 | 5 | 1. 它最适合于具有以下特征的应用程序:Set 大小通常保持很小,只读操作远多于可变操作,需要在遍历期间防止线程间的冲突。 6 | 2. 它是线程安全的。 7 | 3. 因为通常需要复制整个基础数组,所以可变操作(add()、set() 和 remove() 等等)的开销很大。 8 | 4. 迭代器支持hasNext(), next()等不可变操作,但不支持可变 remove()等 操作。 9 | 5. 使用迭代器进行遍历的速度很快,并且不会与其他线程发生冲突。在构造迭代器时,迭代器依赖于不变的数组快照。 10 | 11 | #### 二、原理和数据结构 12 | 13 | ![1545469154761](assets/1545469154761.png) 14 | 15 | **说明**: 16 | 17 | 1. CopyOnWriteArraySet继承于AbstractSet,这就意味着它是一个集合。 18 | 2. CopyOnWriteArraySet包含CopyOnWriteArrayList对象,它是通过CopyOnWriteArrayList实现的。而CopyOnWriteArrayList本质是个动态数组队列, **所以CopyOnWriteArraySet相当于通过通过动态数组实现的“集合”**! CopyOnWriteArrayList中允许有重复的元素;但是,CopyOnWriteArraySet是一个集合,所以它不能有重复集合。因此,CopyOnWriteArrayList额外提供了**addIfAbsent()**和**addAllAbsent()**这两个添加元素的API,通过这些API来添加元素时,只有当元素不存在时才执行添加操作! 19 | 3. 至于CopyOnWriteArraySet的“线程安全”机制,和CopyOnWriteArrayList一样,是通过volatile和互斥锁来实现的。 20 | 21 | #### 三、方法列表 22 | 23 | ```java 24 | // 创建一个空 set。 25 | CopyOnWriteArraySet() 26 | // 创建一个包含指定 collection 所有元素的 set。 27 | CopyOnWriteArraySet(Collection c) 28 | 29 | // 如果指定元素并不存在于此 set 中,则添加它。 30 | boolean add(E e) 31 | // 如果此 set 中没有指定 collection 中的所有元素,则将它们都添加到此 set 中。 32 | boolean addAll(Collection c) 33 | // 移除此 set 中的所有元素。 34 | void clear() 35 | // 如果此 set 包含指定元素,则返回 true。 36 | boolean contains(Object o) 37 | // 如果此 set 包含指定 collection 的所有元素,则返回 true。 38 | boolean containsAll(Collection c) 39 | // 比较指定对象与此 set 的相等性。 40 | boolean equals(Object o) 41 | // 如果此 set 不包含任何元素,则返回 true。 42 | boolean isEmpty() 43 | // 返回按照元素添加顺序在此 set 中包含的元素上进行迭代的迭代器。 44 | Iterator iterator() 45 | // 如果指定元素存在于此 set 中,则将其移除。 46 | boolean remove(Object o) 47 | // 移除此 set 中包含在指定 collection 中的所有元素。 48 | boolean removeAll(Collection c) 49 | // 仅保留此 set 中那些包含在指定 collection 中的元素。 50 | boolean retainAll(Collection c) 51 | // 返回此 set 中的元素数目。 52 | int size() 53 | // 返回一个包含此 set 所有元素的数组。 54 | Object[] toArray() 55 | // 返回一个包含此 set 所有元素的数组;返回数组的运行时类型是指定数组的类型。 56 | T[] toArray(T[] a) 57 | ``` 58 | 59 | #### 四、源码分析 60 | 61 | CopyOnWriteArraySet是通过CopyOnWriteArrayList实现的,它的API基本上都是通过调用CopyOnWriteArrayList的API来实现的。相信对CopyOnWriteArrayList了解的话,对CopyOnWriteArraySet的了解是水到渠成的事;所以,这里只看一下add方法是如何实现元素唯一的: 62 | 63 | ![1545469782495](assets/1545469782495.png) 64 | 65 | add方法中调用了addIfAbsent(E e)方法: 66 | 67 | ![1545469983372](assets/1545469983372.png) 68 | 69 | 判断一下元素e在数组中是否存在,存在的话就返回false,不存在的话调用addIfAbsent(E e, Object[] snapshot)方法进行元素的添加: 70 | 71 | ![1545470151479](assets/1545470151479.png) 72 | 73 | 首先获取锁,然后比较传过来的数组snapshot和"volatile数组"是否完全相同,因为此时可能有其它线程刚对"volatile数组"添加完元素e,使用"!="进行比较就是为了判断两个指针是否指向同一地址: 74 | 75 | - 不相同的话,先得到两个数组长度的最小值,紧接着获取current里面改变后的元素,使用eq方法判断是否和e相等。对未比较过的元素执行indexof方法,要是有重复的话就返回false。 76 | - 相同的话就新建一个数组,然后将元素e插入,将新数组赋值给"volatile数组",最后再释放锁。 77 | 78 | 以上两个方法都是CopyOnWriteArrayList中的。 79 | 80 | #### 五、使用 81 | 82 | ```java 83 | package com.juc.copyonwritearrayset; 84 | 85 | import java.lang.reflect.Field; 86 | import java.util.concurrent.CopyOnWriteArrayList; 87 | import java.util.concurrent.CopyOnWriteArraySet; 88 | 89 | /** 90 | * @Author: 98050 91 | * @Time: 2018-12-22 16:50 92 | * @Feature: copyOnWriteArraySet的使用 93 | */ 94 | public class Test { 95 | 96 | public static void main(String[] args) throws InterruptedException, NoSuchFieldException, IllegalAccessException { 97 | 98 | final CopyOnWriteArraySet list = new CopyOnWriteArraySet(); 99 | 100 | /** 101 | * 线程1将0——9填充到set中 102 | */ 103 | new Thread(new Runnable() { 104 | @Override 105 | public void run() { 106 | for (int i = 0; i < 10; i++) { 107 | try { 108 | Thread.sleep(10); 109 | } catch (InterruptedException e) { 110 | e.printStackTrace(); 111 | } 112 | list.add(i); 113 | } 114 | } 115 | }).start(); 116 | 117 | 118 | /** 119 | * 线程2将10——19填充到set中 120 | */ 121 | new Thread(new Runnable() { 122 | @Override 123 | public void run() { 124 | for (int i = 10; i < 20; i++) { 125 | try { 126 | Thread.sleep(10); 127 | } catch (InterruptedException e) { 128 | e.printStackTrace(); 129 | } 130 | list.add(i); 131 | } 132 | } 133 | }).start(); 134 | 135 | Thread.sleep(1000); 136 | 137 | 138 | Class calss = (Class) list.getClass(); 139 | Field field = calss.getDeclaredField("al"); 140 | field.setAccessible(true); 141 | CopyOnWriteArrayList copyOnWriteArrayList = (CopyOnWriteArrayList) field.get(list); 142 | 143 | Class calss2 = (Class) copyOnWriteArrayList.getClass(); 144 | Field field2 = calss2.getDeclaredField("array"); 145 | field2.setAccessible(true); 146 | Object[] objects = (Object[]) field2.get(copyOnWriteArrayList); 147 | 148 | System.out.println("list的容量:" + objects.length); 149 | for (int i = 0; i < objects.length; i++) { 150 | System.out.println("第"+(i+1)+"个元素:" + objects[i]); 151 | } 152 | } 153 | } 154 | ``` 155 | 156 | 结果: 157 | 158 | ![1545553939762](assets/1545553939762.png) -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——LinkedBlockingDeque.md: -------------------------------------------------------------------------------- 1 | ### 一、介绍 2 | 3 | ### 二、原理和数据结构 4 | 5 | ### 三、方法列表 6 | 7 | ### 四、源码分析 8 | 9 | ### 五、使用 -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——LinkedBlockingQueue.md: -------------------------------------------------------------------------------- 1 | ### 一、介绍 2 | 3 | ### 二、原理和数据结构 4 | 5 | ### 三、方法列表 6 | 7 | ### 四、源码分析 8 | 9 | ### 五、使用 -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——LinkedTransferQueue.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/JUC集合——LinkedTransferQueue.md -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——PriorityQueue.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/JUC集合——PriorityQueue.md -------------------------------------------------------------------------------- /并发编程/JUC集合/JUC集合——框架.md: -------------------------------------------------------------------------------- 1 | ### 一、Java集合包 2 | 3 | 主体内容包括Collection集合和Map类;而Collection集合又可以划分为List(队列)和Set(集合)。 4 | 5 | #### 1.1 List的实现类 6 | 7 | 主要有以下几种: 8 | 9 | 1. LinkedList是双向链表实现的双端队列,**不是线程安全的**,只适用于单线程。 10 | 2. ArrayList是数组实现的队列,它是一个动态数组,**不是线程安全的**,只适用于单线程。 11 | 3. Vector是数组实现的矢量队列,它也一个动态数组,不过和ArrayList不同的是,**Vector是线程安全的**,它支持并发。 12 | 4. Stack是Vector实现的栈;和Vector一样,它也是**线程安全的**。 13 | 14 | #### 1.2 Set的实现类 15 | 16 | 主要有以下几种: 17 | 18 | 1. HashSet是一个没有重复元素的集合,它通过HashMap实现的;**HashSet不是线程安全的**,只适用于单线程。 19 | 2. TreeSet也是一个没有重复元素的集合,不过和HashSet不同的是,**TreeSet中的元素是有序的**;它是通过TreeMap实现的;**TreeSet也不是线程安全的**,只适用于单线程。 20 | 21 | #### 1.3 Map的实现类 22 | 23 | 主要有以下几种: 24 | 25 | 1. HashMap是存储“键-值对”的哈希表;**它不是线程安全的**,只适用于单线程。 26 | 2. WeakHashMap是也是哈希表,和HashMap不同的是,**HashMap的“键”是强引用类型**,而**WeakHashMap的“键”是弱引用类型**,也就是说当WeakHashMap 中的某个键不再正常使用时,会被从WeakHashMap中被自动移除。**WeakHashMap也不是线程安全的**,只适用于单线程。 27 | 3. HashTable也是哈希表,和HashMap不同的是,HashTable是线程安全的,支持并发。 28 | 4. TreeMap也是哈希表,**不过TreeMap中的“键-值对”是有序的**,它是通过R-B Tree(红黑树)实现的;TreeMap不是线程安全的,只适用于单线程。 29 | 30 | #### 1.4 总结 31 | 32 | 以上Java集合包大多是“非线程安全的”,虽然可以通过Collections工具类中的方法获取java集合包对应的同步类,但是这些同步类的并发效率并不是很高。为了更好的支持高并发任务,相对应的并发容器就产生了。 33 | 34 | JUC包在添加”java集合包“对应的高并发类时,为了保持API接口的一致性,使用了”Java集合包“中的框架。例如,CopyOnWriteArrayList实现了“Java集合包”中的List接口,HashMap继承了“java集合包”中的AbstractMap类,等等。其中最大的难点是,对JUC包是如何添加对“高并发”的支持的! 35 | 36 | ### 二、JUC集合类 37 | 38 | #### 2.1 List和Set 39 | 40 | JUC集合包中的List和Set实现类包括: CopyOnWriteArrayList, CopyOnWriteArraySet和ConcurrentSkipListSet。ConcurrentSkipListSet稍后在说明Map时再说明,CopyOnWriteArrayList 和 CopyOnWriteArraySet的框架如下图所示: 41 | 42 | ![1545368692743](C:\Users\98050\AppData\Local\Temp\1545368692743.png) 43 | 44 | 1. **CopyOnWriteArrayList相当于线程安全的ArrayList**,它实现了List接口。CopyOnWriteArrayList是支持高并发的。 45 | 2. **CopyOnWriteArraySet相当于线程安全的HashSet**,它继承于AbstractSet类。CopyOnWriteArraySet内部包含一个CopyOnWriteArrayList对象,它是通过CopyOnWriteArrayList实现的。 46 | 47 | #### 2.2 Map 48 | 49 | JUC集合包中Map的实现类包括: ConcurrentHashMap和ConcurrentSkipListMap。它们的框架如下图所示: 50 | 51 | ![1545369402415](C:\Users\98050\AppData\Local\Temp\1545369402415.png) 52 | 53 | 1. ConcurrentHashMap是线程安全的哈希表(**相当于线程安全的HashMap**);它继承于AbstractMap类,并且实现ConcurrentMap接口。**ConcurrentHashMap的安全性是通过“锁分段”来实现的**,它支持并发。 54 | 2. ConcurrentSkipListMap是线程安全的有序的哈希表(**相当于线程安全的TreeMap**); 它继承于AbstractMap类,并且实现ConcurrentNavigableMap接口。**ConcurrentSkipListMap的安全性是通过“跳表”来实现的**,它支持并发。 55 | 3. ConcurrentSkipListSet是线程安全的有序的集合(**相当于线程安全的TreeSet**);它继承于AbstractSet,并实现了NavigableSet接口。ConcurrentSkipListSet是通过ConcurrentSkipListMap实现的,它也支持并发。 56 | 57 | #### 2.3 Queue 58 | 59 | JUC集合包中Queue的实现类包括: ArrayBlockingQueue, LinkedBlockingQueue, LinkedBlockingDeque, ConcurrentLinkedQueue和ConcurrentLinkedDeque。它们的框架如下图所示: 60 | 61 | ![1545370249840](C:\Users\98050\AppData\Local\Temp\1545370249840.png) 62 | 63 | 1. ArrayBlockingQueue是数组实现的线程安全的有界的阻塞队列。 64 | 2. LinkedBlockingQueue是单向链表实现的(指定大小)阻塞队列,该队列按 FIFO(先进先出)排序元素。、 65 | 3. LinkedBlockingDeque是双向链表实现的(指定大小)双向并发阻塞队列,该阻塞队列同时支持FIFO和FILO两种操作方式。 66 | 4. ConcurrentLinkedQueue是单向链表实现的非阻塞无界队列,该队列按 FIFO(先进先出)排序元素。 67 | 5. ConcurrentLinkedDeque是双向链表实现的无界队列,该队列同时支持FIFO和FILO两种操作方式。 68 | 69 | -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545396581057.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545396581057.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545396928790.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545396928790.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397658950.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397658950.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397749932.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397749932.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397762923.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397762923.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397804137.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397804137.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397840614.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397840614.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545397887160.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545397887160.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398154642.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398154642.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398582935.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398582935.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398754822.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398754822.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398767573.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398767573.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398798974.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398798974.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398845167.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398845167.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398873596.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398873596.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545398924093.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545398924093.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545404119873.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545404119873.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545468789761.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545468789761.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545469154761.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545469154761.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545469782495.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545469782495.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545469983372.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545469983372.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545470151479.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545470151479.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545548288576.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545548288576.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545553939762.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545553939762.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545919660660.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545919660660.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545976117679.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545976117679.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545976127224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545976127224.png -------------------------------------------------------------------------------- /并发编程/JUC集合/assets/1545976238915.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/JUC集合/assets/1545976238915.png -------------------------------------------------------------------------------- /并发编程/assets/1548339052535.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1548339052535.png -------------------------------------------------------------------------------- /并发编程/assets/1551447554369.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1551447554369.png -------------------------------------------------------------------------------- /并发编程/assets/1551447737059.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1551447737059.png -------------------------------------------------------------------------------- /并发编程/assets/1555751550402.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1555751550402.png -------------------------------------------------------------------------------- /并发编程/assets/1559557555510.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1559557555510.png -------------------------------------------------------------------------------- /并发编程/assets/1559811884338.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/assets/1559811884338.png -------------------------------------------------------------------------------- /并发编程/图库/ArrayList继承关系.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/ArrayList继承关系.png -------------------------------------------------------------------------------- /并发编程/图库/HashMap——putVal方法.eddx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/HashMap——putVal方法.eddx -------------------------------------------------------------------------------- /并发编程/图库/HashMap——putVal方法.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/HashMap——putVal方法.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_14-20-28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_14-20-28.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_14-21-11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_14-21-11.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_16-47-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_16-47-03.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_16-51-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_16-51-17.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_16-52-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_16-52-59.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-34-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-34-38.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-36-32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-36-32.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-37-15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-37-15.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-37-44.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-37-44.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-38-46.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-38-46.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-43-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-43-30.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-43-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-43-35.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-47-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-47-14.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-48-04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-48-04.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-48-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-48-36.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-52-55.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-52-55.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-56-09.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-56-09.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_18-57-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_18-57-30.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-26-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-26-22.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-30-28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-30-28.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-34-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-34-40.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-34-49.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-34-49.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-38-45.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-38-45.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-39-02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-39-02.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-40-26.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-40-26.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-40-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-40-36.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-40-59.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-40-59.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_19-48-51.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_19-48-51.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_20-49-21.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_20-49-21.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_20-49-28.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_20-49-28.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_20-49-36.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_20-49-36.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_20-55-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_20-55-22.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-07-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-07-29.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-09-07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-09-07.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-09-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-09-17.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-10-00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-10-00.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-10-38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-10-38.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-11-23.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-11-23.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-15-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-15-50.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-22-52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-22-52.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-25-53.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-25-53.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-26-03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-26-03.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-26-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-26-35.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-27-22.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-27-22.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-27-52.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-27-52.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_21-28-41.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_21-28-41.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-16-35.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-16-35.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-22-25.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-22-25.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-25-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-25-14.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-29-10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-29-10.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-30-39.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-30-39.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-31-14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-31-14.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-40-19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-40-19.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-41-24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-41-24.png -------------------------------------------------------------------------------- /并发编程/图库/Snipaste_2018-12-21_22-55-17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/图库/Snipaste_2018-12-21_22-55-17.png -------------------------------------------------------------------------------- /并发编程/并发编程基础/1.md: -------------------------------------------------------------------------------- 1 | # 一、线程创建的方式 2 | 3 | ## 1.1 继承Thread类,重写run方法 4 | 5 | ## 1.2 实现Runable接口,重写run方法 6 | 7 | ## 1.3 使用匿名内部类 8 | 9 | 使用实现实现Runnable接口好,原因实现了接口还可以继续继承,继承了类不能再继承。 10 | 11 | # 二、线程分类 12 | 13 | Java中有两种线程,一种是用户线程,另一种是守护线程。 14 | 15 | 用户线程是指用户自定义创建的线程,主线程停止,用户线程不会停止 16 | 17 | 守护线程当进程不存在或主线程停止,守护线程也会被停止。 18 | 19 | 使用setDaemon(true)方法设置为守护线程 20 | 21 | # 三、线程运行状态 22 | 23 | 线程从创建、运行到结束总是处于下面五个状态之一:新建状态、就绪状态、运行状态、阻塞状态及死亡状态。 24 | 25 | ![](http://mycsdnblog.work/201919052036-q.png) 26 | 27 | ## 3.1 操作系统中的线程和Java线程状态的关系 28 | 29 | 从实际意义上来讲,操作系统中的线程除去new和terminated状态,一个线程真实存在的状态,只有: 30 | 31 | - ready:表示线程已经被创建,正在等待系统调度分配CPU使用权。 32 | - running:表示线程获得了CPU使用权,正在进行运算 33 | - waiting:表示线程等待(或者说挂起),让出CPU资源给其他线程使用 34 | 35 | **为什么除去new和terminated状态?是因为这两种状态实际上并不存在于线程运行中,所以也没什么实际讨论的意义。** 36 | 37 | 对于Java中的线程状态: 38 | 39 | **无论是Timed Waiting ,Waiting还是Blocked,对应的都是操作系统线程的waiting(等待)状态。** 40 | 41 | **而Runnable状态,则对应了操作系统中的ready和running状态。** 42 | 43 | 而对不同的操作系统,由于本身设计思路不一样,对于线程的设计也存在种种差异,所以JVM在设计上,就已经声明: 44 | 45 | **虚拟机中的线程状态,不反应任何操作系统线程状态** 46 | 47 | # 四、join()方法 48 | 49 | 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1 50 | 51 | # 五、线程优先级 52 | 53 | 在JAVA线程中,通过一个int priority来控制优先级,范围为1-10,其中10最高,默认值为5。 54 | 55 | **注意设置了优先级, 不代表每次都一定会被执行。 只是CPU调度会有限分配** 56 | 57 | # 六、yield方法 58 | 59 | Thread.yield()方法的作用:暂停当前正在执行的线程,并执行其他线程。(可能没有效果) 60 | 61 | yield()让当前正在运行的线程回到可运行状态,以允许具有相同优先级的其他线程获得运行的机会。因此,使用yield()的目的是让具有相同优先级的线程之间能够适当的轮换执行。但是,实际中无法保证yield()达到让步的目的,因为,让步的线程可能被线程调度程序再次选中。 62 | 63 | 结论:大多数情况下,yield()将导致线程从运行状态转到可运行状态,但有可能没有效果。 64 | 65 | # 七、start和run的区别 66 | 67 | **直接调用run方法是无法开启一个新线程的。start方法其实是在一个新的操作系统线程上面去调用run方法。换句话说,直接调用run方法而不是调用start方法的话,它并不会开启新的线程,而是在调用run的当前的线程当中执行你的操作。** -------------------------------------------------------------------------------- /并发编程/并发编程基础/2.md: -------------------------------------------------------------------------------- 1 | # 一、什么是线程安全问题 2 | 3 | 当多个线程同时共享,同一个**全局变量或静态变量**,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。 4 | 5 | # 二、线程安全问题的解决方法 6 | 7 | 线程同步或者加锁 8 | 9 | **将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,让后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。** 10 | 11 | **当多个线程共享同一个资源,不会受到其他线程的干扰。** ——同步 12 | 13 | # 三、synchronized内置锁 14 | 15 | synchronized 16 | 17 | 同步代码块 18 | 19 | 同步方法 20 | 21 | 普通同步方法使用this锁 22 | 23 | 静态同步方法使用该方法字节码文件对象锁 24 | 25 | synchronized 修饰方法使用锁是当前this锁。 26 | 27 | synchronized 修饰静态方法使用锁是当前类的字节码文件 28 | 29 | # 四、多线程死锁 30 | 31 | 同步中嵌套同步,导致锁无法释放 32 | 33 | # 五、ThreadLocal 34 | 35 | ThreadLocal是如何为每个线程创建变量的副本的: 36 | 37 |   首先,在每个线程Thread内部有一个ThreadLocal.ThreadLocalMap类型的成员变量threadLocals,这个threadLocals就是用来存储实际的变量副本的,键值为当前ThreadLocal变量,value为变量副本(即T类型的变量)。 38 | 39 |   初始时,在Thread里面,threadLocals为空,当通过ThreadLocal变量调用get()方法或者set()方法,就会对Thread类中的threadLocals进行初始化,并且以当前ThreadLocal变量为键值,以ThreadLocal要保存的副本变量为value,存到threadLocals。 40 | 41 |   然后在当前线程里面,如果要使用副本变量,就可以通过get方法在threadLocals里面查找。 42 | 43 | ThreadLocal提高一个线程的局部变量,访问某个线程拥有自己局部变量。当使用ThreadLocal维护变量时,ThreadLocal为每个使用该变量的线程提供独立的变量副本,所以每一个线程都可以独立地改变自己的副本,而不会影响其它线程所对应的副本。 44 | 45 | 实现原理: 46 | 47 | ThreadLocal通过map集合 48 | 49 | Map.put(“当前线程”,值); 50 | 51 | ThreadLocal中解决冲突的策略是使用的线性探测法 52 | 53 | ThreadLocalMap解决Hash冲突的方式就是简单的步长加1或减1,寻找下一个相邻的位置。处理hash冲突的效率低,**所以,每个线程只存一个变量,这样的话所有的线程存放到map中的Key都是相同的ThreadLocal,如果一个线程要保存多个变量,就需要创建多个ThreadLocal,多个ThreadLocal放入Map中时会极大的增加Hash冲突的可能。** 54 | 55 | 每个线程都有一个ThreadLoalMap 56 | 57 | ![1551447554369](assets/1551447554369.png) 58 | 59 | #### ThreadLocalMap的问题 60 | 61 | ![1551447737059](assets/1551447737059.png) 62 | 63 | 由于ThreadLocalMap的key是弱引用,而Value是强引用。这就导致了一个问题,ThreadLocal在没有外部对象强引用时,发生GC时弱引用Key会被回收,而Value不会回收,如果创建ThreadLocal的线程一直持续运行,那么这个Entry对象中的value就有可能一直得不到回收,发生内存泄露。 64 | 65 | **如何避免泄漏** 66 | 既然Key是弱引用,那么我们要做的事,**就是在调用ThreadLocal的get()、set()方法时完成后再调用remove方法,将Entry节点和Map的引用关系移除**,这样整个Entry对象在GC Roots分析后就变成不可达了,下次GC的时候就可以被回收。 67 | 68 | 如果使用ThreadLocal的set方法之后,没有显示的调用remove方法,就有可能发生内存泄露,所以养成良好的编程习惯十分重要,**使用完ThreadLocal之后,记得调用remove方法**。 69 | 70 | ------ 71 | 72 | **设计成弱引用的目的是为了更好地对ThreadLocal进行回收,当我们在代码中将ThreadLocal的强引用置为null后,这时候Entry中的ThreadLocal理应被回收了,但是如果Entry的key被设置成强引用则该ThreadLocal就不能被回收,这就是将其设置成弱引用的目的。** 73 | 74 | # 六、多线程的三大特性 75 | 76 | ## 6.1 原子性 77 | 78 | 即一个操作或者多个操作 要么全部执行并且执行的过程不会被任何因素打断,要么就都不执行。 79 | 80 | ## 6.2 可见性 81 | 82 | 当多个线程访问同一个变量时,一个线程修改了这个变量的值,其他线程能够立即看得到修改的值。 83 | 84 | ## 6.3 有序性 85 | 86 | # 七、Java内存模型 87 | 88 | 共享内存模型指的就是Java内存模型(简称JMM),**JMM决定一个线程对共享变量的写入时,能对另一个线程可见**。从抽象的角度来看,**JMM定义了线程和主内存之间的抽象关系**:线程之间的共享变量存储在主内存(main memory)中,每个线程都有一个私有的本地内存(local memory),本地内存中存储了该线程以读/写共享变量的副本。本地内存是JMM的一个抽象概念,并不真实存在。它涵盖了缓存,写缓冲区,寄存器以及其他的硬件和编译器优化。 89 | 90 | ![1548339052535](assets/1548339052535.png) 91 | 92 | Java内存模型简称JMM,定义了一个线程对另一个线程可见。共享变量存放在主内存中,每个线程都有自己的本地内存,当多个线程同时访问一个数据的时候,可能本地内存没有及时刷新到主内存,所以就会发生线程安全问题。 93 | 94 | # 八、volatile 95 | 96 | 可见性也就是说一旦某个线程修改了该被volatile修饰的变量,它会保证修改的值会立即被更新到主存,当有其他线程需要读取时,可以立即获取修改之后的值。 97 | 98 | 在Java中为了加快程序的运行效率,对一些变量的操作通常是在该线程的寄存器或是CPU缓存上进行的,之后才会同步到主存中,而加了volatile修饰符的变量则是直接读写主存。 99 | 100 | volatile 保证了线程间共享变量的及时可见性,但不能保证原子性 101 | 102 | 1.保证此变量对所有的线程的可见性,这里的“可见性”,当一个线程修改了这个变量的值,volatile 保证了新值能立即同步到主内存,以及每次使用前立即从主内存刷新。但普通变量做不到这点,普通变量的值在线程间传递均需要通过主内存(详见:Java内存模型)来完成。 103 | 104 | 2.禁止指令重排序优化。有volatile修饰的变量,赋值后多执行了一个“load addl $0x0, (%esp)”操作,这个操作相当于一个内存屏障(指令重排序时不能把后面的指令重排序到内存屏障之前的位置),只有一个CPU访问内存时,并不需要内存屏障;(什么是指令重排序:是指CPU采用了允许将多条指令不按程序规定的顺序分开发送给各相应电路单元处理)。 105 | 106 | volatile 性能: 107 | 108 |   volatile 的读性能消耗与普通变量几乎相同,但是写操作稍慢,因为它需要在本地代码中插入许多内存屏障指令来保证处理器不发生乱序执行。 109 | 110 | # 九、volatile与synchronized区别 111 | 112 | ## 9.1 synchronized保证可见性和操作的原子性 113 | 114 | `Synchronized实现原子性和可见性的原理`: 115 | 116 | 在Java内存模型中,synchronized规定,线程在`加锁时`,先清空工作内存→在主内存中拷贝最新变量的副本到工作内存→执行完代码→将更改后的共享变量的值刷新到主内存中→`释放互斥锁`。 117 | 118 | ## 9.2 volatile保证可见性但不保证原子性 119 | 120 | `Volatile 保证可见性的原理`: 121 | 122 | Volatile实现内存可见性`是通过store和load指令完成的`;也就是`对volatile变量执行写操作时`,会在`写操作`后加入一条`store指令`,即`强迫线程将最新的值刷新到主内存中`;而在`读操作`时,会加入一条`load指令`,即`强迫从主内存中读入变量的值`。 123 | 124 | ------ 125 | 126 | (1)从而我们可以看出volatile虽然具有可见性但是并不能保证原子性。 127 | 128 | (2)性能方面,synchronized关键字是防止多个线程同时执行一段代码,就会影响程序执行效率,而volatile关键字在某些情况下性能要优于synchronized。 129 | 130 | 但是要注意volatile关键字是无法替代synchronized关键字的,因为volatile关键字无法保证操作的原子性。 131 | 132 | -------------------------------------------------------------------------------- /并发编程/并发编程基础/3.md: -------------------------------------------------------------------------------- 1 | # 一、多线程之间通讯 2 | 3 | 多线程之间通讯,其实就是多个线程在操作同一个资源,但是操作的动作不同。 4 | 5 | # 二、生产者-消费者 6 | 7 | 8 | 9 | # 三、wait、notify方法 10 | 11 | 1.因为涉及到对象锁,他们必须都放在synchronized中来使用. Wait、Notify一定要在synchronized里面进行使用。 12 | 13 | 2.Wait必须暂停当前正在执行的线程,并释放资源锁,让其他线程可以有机会运行 14 | 15 | 3.notify/notifyall: 唤醒因锁池中的线程,使之运行 16 | 17 | **注意:一定要在线程同步中使用,并且是同一个锁的资源** 18 | 19 | 需要线程通讯标识 20 | 21 | # 四、wait与sleep区别 22 | 23 | 对于sleep()方法,我们首先要知道该方法是属于Thread类中的。而wait()方法,则是属于Object类中的。 24 | 25 | sleep()方法导致了程序暂停执行指定的时间,让出cpu该其他线程,但是他的监控状态依然保持者,当指定的时间到了又会自动恢复运行状态。 26 | 27 | 在调用sleep()方法的过程中,线程不会释放对象锁。 28 | 29 | 而当调用wait()方法的时候,线程会放弃对象锁,进入等待此对象的等待锁定池,只有针对此对象调用notify()方法后本线程才进入对象锁定池准备获取对象锁进入运行状态。 30 | 31 | # 五、Lock锁 32 | 33 | 在 jdk1.5 之后,并发包中新增了 Lock 接口(以及相关实现类)用来实现锁功能,Lock 接口提供了与 synchronized 关键字类似的同步功能,但需要在使用时手动获取锁和释放锁。 34 | 35 | ```java 36 | Lock lock = new ReentrantLock(); 37 | lock.lock(); 38 | try{ 39 | //可能会出现线程安全的操作 40 | }finally{ 41 | //一定在finally中释放锁 42 | //也不能把获取锁在try中进行,因为有可能在获取锁的时候抛出异常 43 | lock.ublock(); 44 | } 45 | ``` 46 | 47 | 可重入锁 48 | 49 | AbstractQueuedSynchronizer:抽象队列同步器 50 | 51 | ReentrantLock内部有一个AQS对象 52 | 53 | AQS对象内部有一个核心变量state,int类型,代表了加锁状态 初始值时,state = 0; 54 | 55 | AQS内部还有一个核心变量,用来记录当前加锁的是哪个线程 56 | 57 | 58 | 59 | 线程1:加锁过程就是利用CAS操作将state变为1,当前线程变为线程1 60 | 61 | 线程2:加锁,发现state不为0,然后再查看是不是自己加的锁,发现不是,那么就加锁失败,线程2将自己放入AQS中的一个等待队列 62 | 63 | 当线程1释放锁后,从等待队列头获取一个线程进行加锁 64 | 65 | # 六、Lock与synchronized关键字的区别 66 | 67 | Lock 接口可以尝试非阻塞地获取锁 当前线程尝试获取锁。如果这一时刻锁没有被其他线程获取到,则成功获取并持有锁。 68 | Lock 接口能被中断地获取锁 与 synchronized 不同,获取到锁的线程能够响应中断,当获取到的锁的线程被中断时,中断异常将会被抛出,同时锁会被释放。 69 | 70 | Lock 接口在指定的截止时间之前获取锁,如果截止时间到了依旧无法获取锁,则返回。 71 | 72 | 73 | 74 | 1)Lock是一个接口,而synchronized是Java中的关键字,synchronized是内置的语言实现; 75 | 76 | 2)synchronized在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用Lock时需要在finally块中释放锁; 77 | 78 | 3)Lock可以让等待锁的线程响应中断,而synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断; 79 | 80 | 4)通过Lock可以知道有没有成功获取锁,而synchronized却无法办到。 81 | 82 | 5)Lock可以提高多个线程进行读操作的效率。 83 | 84 |   在性能上来说,如果竞争资源不激烈,两者的性能是差不多的,而当竞争资源非常激烈时(即有大量线程同时竞争),此时Lock的性能要远远优于synchronized。所以说,在具体使用时要根据适当情况选择。 85 | 86 | # 七、wait与join的区别 87 | 88 | join方法在调用wait方法后, 并没有执行notify方法, 这个是在jvm中实现的, 一个线程执行结束后会执行该线程自身对象的notifyAll方法 -------------------------------------------------------------------------------- /并发编程/并发编程基础/4.md: -------------------------------------------------------------------------------- 1 | # 一、死锁检测 2 | 3 | ```java 4 | package com.example.deadlock; 5 | 6 | /** 7 | * @Author: 98050 8 | * @Time: 2019-05-23 14:30 9 | * @Feature: 10 | */ 11 | public class DeadLockDemo { 12 | 13 | private static String A = "A"; 14 | private static String B = "B"; 15 | 16 | public static void main(String[] args) { 17 | new DeadLockDemo().deadLock(); 18 | } 19 | 20 | private void deadLock(){ 21 | new Thread(new Runnable() { 22 | public void run() { 23 | synchronized (A) { 24 | try { 25 | Thread.sleep(2000); 26 | } catch (InterruptedException e) { 27 | e.printStackTrace(); 28 | } 29 | synchronized (B){ 30 | System.out.println(1); 31 | } 32 | } 33 | } 34 | }).start(); 35 | 36 | new Thread(new Runnable() { 37 | public void run() { 38 | synchronized (B) { 39 | try { 40 | Thread.sleep(2000); 41 | } catch (InterruptedException e) { 42 | e.printStackTrace(); 43 | } 44 | synchronized (A){ 45 | System.out.println(2); 46 | } 47 | } 48 | } 49 | }).start(); 50 | } 51 | } 52 | ``` 53 | 54 | 使用Jconsole: 55 | 56 | ![](http://mycsdnblog.work/201919231456-6.png) 57 | 58 | ![](http://mycsdnblog.work/201919231456-Z.png) -------------------------------------------------------------------------------- /并发编程/并发编程基础/assets/1559120626687.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/并发编程基础/assets/1559120626687.png -------------------------------------------------------------------------------- /并发编程/并发编程基础/assets/1559201658664.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/并发编程基础/assets/1559201658664.png -------------------------------------------------------------------------------- /并发编程/并发编程基础/assets/1559201686917.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/并发编程基础/assets/1559201686917.png -------------------------------------------------------------------------------- /并发编程/并发编程基础/并发——锁.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/并发编程基础/并发——锁.pdf -------------------------------------------------------------------------------- /并发编程/锁的膨胀过程.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/并发编程/锁的膨胀过程.png -------------------------------------------------------------------------------- /数据结构/LCS、LIS、LICS.md: -------------------------------------------------------------------------------- 1 | # 一、最长公共子串 2 | 3 | 问题:有两个字符串str1和str2,求出两个字符串中最长公共子串长度。 4 | 5 | 例子:str1=acbcbcef,str2=abcbced,则str和str2的最长公共子串为bcbce,最长公共子串长度为5。 6 | 7 | **思路:** 8 | 9 | 1、把两个字符串分别以行和列组成一个二维矩阵。 10 | 11 | 2、比较二维矩阵中每个点对应行列字符中否相等,相等的话值设置为1,否则设置为0。 12 | 13 | 3、通过查找出值为1的最长对角线就能找到最长公共子串。 14 | 15 | 矩阵: 16 | 17 | ![](http://mycsdnblog.work/201919151944-Q.png) 18 | 19 | 从上图可以看到,str1和str2共有5个公共子串,但最长的公共子串长度为5。 20 | 21 | 为了进一步优化算法的效率,我们可以再计算某个二维矩阵的值的时候顺便计算出来当前最长的公共子串的长度,这样就避免了后续查找对角线长度的操作了。修改后的二维矩阵如下: 22 | 23 | ![](http://mycsdnblog.work/201919151945-i.png) 24 | 25 | 代码: 26 | 27 | ```java 28 | private static String subStr(String str1, String str2) { 29 | int row = str1.length(); 30 | int col = str2.length(); 31 | int[][] result = new int[row][col]; 32 | int maxLength = 0; 33 | int end = 0; 34 | for (int i = 0; i < row; i++) { 35 | for (int j = 0; j < col; j++) { 36 | if (str1.charAt(i) == str2.charAt(j)){ 37 | if (i == 0 || j == 0){ 38 | result[i][j] = 1; 39 | }else { 40 | result[i][j] = result[i - 1][j - 1] + 1; 41 | } 42 | } 43 | if (result[i][j] > maxLength){ 44 | maxLength = result[i][j]; 45 | end = j; 46 | } 47 | } 48 | } 49 | return str2.substring(end - maxLength + 1, end + 1); 50 | } 51 | ``` 52 | 53 | 通过记录最大长度,以及最大长度的位置,来截取最后的字符串 54 | 55 | # 二、最长公共子序列(LCS) 56 | 57 | 子序列可以不连续,所以在状态转移方程上有所改变: 58 | 59 | ![](http://mycsdnblog.work/201919152028-0.png) 60 | 61 | 如果两个对应字符相等,那么依然是C[i-1,j-1]+1,如果不相同的话,为了保持上一个相同的状态,那么就需要复制上一个状态,上一个状态在哪里?就是在当前位置的**左侧和上侧**,这两个里面取最大的即可。 62 | 63 | ![](http://mycsdnblog.work/201919152102-b.png) 64 | 65 | 代码: 66 | 67 | ```java 68 | private static int subStr(String str1, String str2) { 69 | int row = str1.length() + 1; 70 | int col = str2.length() + 1; 71 | int[][] result = new int[row][col]; 72 | for (int i = 1; i < row; i++) { 73 | for (int j = 1; j < col; j++) { 74 | if (str1.charAt(i - 1) == str2.charAt(j - 1)){ 75 | result[i][j] = result[i - 1][j - 1] + 1; 76 | }else { 77 | result[i][j] = Math.max(result[i-1][j],result[i][j-1]); 78 | } 79 | } 80 | } 81 | return result[row - 1][col - 1]; 82 | } 83 | ``` 84 | 85 | 通过result数组,回溯法找到所有子序列。 86 | 87 | # 三、最长递增子序列(LIS) 88 | 89 | # 四、最长递增公共子序列 90 | 91 | -------------------------------------------------------------------------------- /数据结构/位图法.md: -------------------------------------------------------------------------------- 1 | # 一、定义 2 | 3 | 位图法就是bitmap的缩写。所谓bitmap,就是用每一位来存放某种状态,适用于大规模数据,但数据状态又不是很多的情况。通常是用来判断某个数据存不存在的。 4 | 5 | # 二、数据结构 6 | 7 | 我们用一个具体的例子来讲解,假设我们要对0-7内的5个元素(4,7,2,5,3)排序(这里假设这些元素没有重复)。那么我们就可以采用BitMap的方法来达到排序的目的。要表示8个数,我们就只需要8个bit(1Bytes)。 8 | (1)首先我们开辟1字节(8bit)的空间,将这些空间的所有bit位都置为0,如下图: 9 | 10 | ![这里写图片描述](https://img-blog.csdn.net/20150207143647124) 11 | 12 | (2)然后遍历这5个元素,首先第1个元素是4,那么就把4对应的位置为1,因为是从零开始的,所以要把第5个位置为1(如下图): 13 | 14 | ![这里写图片描述](https://img-blog.csdn.net/20150207143740102) 15 | 16 | 然后再处理第2个元素7,将第8个位置为1,,接着再处理第3个元素,一直到处理完所有元素,将相应的位置为1,这时候的内存的bit位的状态如下: 17 | 18 | ![这里写图片描述](https://img-blog.csdn.net/20150207143819256) 19 | 20 | (3)然后我们现在遍历一遍bit区域,将该位是1的位的编号输出(2,3,4,5,7),这样就达到了排序的目的。 21 | 22 | 算法思想比较简单,但关键是如何确定十进制的数映射到二进制bit位的map图。 23 | 24 | # 三、Map映射 25 | 26 | 假设需要排序或者查找的总数N=10000000。 27 | 28 | BitMap中1bit代表一个数字 29 | 30 | 1个int = 4Bytes = 4*8bit = 32 bit,那么N个数需要N/32 int空间。所以我们需要申请内存空间的大小为int a[1 + N/32],其中:a[0]在内存中占32为可以对应十进制数0-31,依次类推: 31 | 32 | BitMap表为: 33 | 34 | ``` 35 | a[0] ---------> 0-31 36 | a[1] ---------> 32-63 37 | a[2] ---------> 64-95 38 | a[3] ---------> 96-127 39 | .......... 40 | ``` 41 | 42 | 那么十进制数如何转换为对应的bit位,下面介绍用位移将十进制数转换为对应的bit位。 43 | 44 | 申请一个int一维数组,那么可以当作为列为32位的二维数组。 45 | 46 | ![](http://mycsdnblog.work/201919291535-S.png) 47 | 48 | 例如: 49 | 十进制1 在a[0]中,位置如下图: 50 | ![这里写图片描述](https://img-blog.csdn.net/20150207150658412) 51 | 十进制31 在a[0]中,位置如下图: 52 | ![这里写图片描述](https://img-blog.csdn.net/20150207150846177) 53 | 十进制32 在a[1]中,位置如下图: 54 | ![这里写图片描述](https://img-blog.csdn.net/20150207150937127) 55 | 十进制33 在a[1]中,位置如下图: 56 | ![这里写图片描述](https://img-blog.csdn.net/20150207151111539) 57 | 58 | 通过上图分析得出通过以下几步将十进制数如何转换为对应的bit位: 59 | 60 | **(1)求十进制数在对应数组a中的下标** 61 | 62 | 十进制数0-31,对应在数组a[0]中,32-63对应在数组a[1]中,64-95对应在数组a[2]中……… 63 | 64 | **分析得出:对于一个十进制数n,对应在数组a[n/32]中** 65 | 66 | 例如n=11,那么 n/32=0,则11对应在数组a中的下标为0,n=32,那么n/32=1,则32对应在数组a中的下标为1,n = 106,那么n/32 = 3,则106对应数组a中的下标为3。 67 | 68 | **(2)求十进制数在对应数组a[i]中的下标** 69 | 70 | 例如十进制数1在a[0]的下标为1,十进制数31在a[0]中下标为31,十进制数32在a[1]中下标为0。 71 | 在十进制0-31就对应0-31,而32-63则对应也是0-31,即给定一个数n可以通过模32求得在对应数组a[i]中的下标。 72 | **分析得出:对于一个十进制数n,对应在数组`a[n/32]`中** 73 | 74 | **(3)移位** 75 | 76 | 对于一个十进制数n,对应在数组`a[n/32][n%32]`中,但数组a毕竟不是一个二维数组,我们通过移位操作实现置1。 77 | a[n/32] |= 1 << n % 32 78 | 79 | 移位操作: 80 | 81 | a[n>>5] |= 1 << (n & 0x1F) 82 | 83 | n & 0x1F 保留n的后五位 相当于 n % 32 求十进制数在数组a[i]中的下标 84 | 85 | # 四、位图法的缺点 86 | 87 | 1. 可读性差 88 | 2. 位图存储的元素个数虽然比一般做法多,但是存储的元素大小受限于存储空间的大小。位图存储性质:存储的元素个数等于元素的最大值。比如, 1K 字节内存,能存储 8K 个值大小上限为 8K 的元素。(元素值上限为 8K ,这个局限性很大!)比如,要存储值为 65535 的数,就必须要 65535/8=8K 字节的内存。要就导致了位图法根本不适合存 unsigned int 类型的数(大约需要 2^32/8=5 亿字节的内存)。 89 | 3. 位图对有符号类型数据的存储,需要 2 位来表示一个有符号元素。这会让位图能存储的元素个数,元素值大小上限减半。 比如 8K 字节内存空间存储 short 类型数据只能存 8K*4=32K 个,元素值大小范围为 -32K~32K 。 90 | 91 | # 五、位图法的应用 92 | 93 | 1、给40亿个不重复的unsigned int的整数,没排过序的,然后再给一个数,如何快速判断这个数是否在那40亿个数当中。 94 |   首先,将这40亿个数字存储到bitmap中,然后对于给出的数,判断是否在bitmap中即可。 95 | 96 | 2、使用位图法判断整形数组是否存在重复 97 | 98 | 遍历数组,一个一个放入bitmap,并且检查其是否在bitmap中出现过,如果没出现放入,否则即为重复的元素。 99 | 100 | 3、使用位图法进行整形数组排序 101 | 102 | 首先遍历数组,得到数组的最大最小值,然后根据这个最大最小值来缩小bitmap的范围。这里需要注意对于int的负数,都要转化为unsigned int来处理,而且取位的时候,数字要减去最小值。 103 | 104 | 4、在2.5亿个整数中找出不重复的整数,注,内存不足以容纳这2.5亿个整数 105 | 106 | 参 考的一个方法是:采用2-Bitmap(每个数分配2bit,00表示不存在,01表示出现一次,10表示多次,11无意义)。其实,这里可以使用两个普 通的Bitmap,即第一个Bitmap存储的是整数是否出现,如果再次出现,则在第二个Bitmap中设置即可。这样的话,就可以使用简单的1- Bitmap了。 107 | 108 | 5、排序 109 | 110 | 6、快速去重 111 | 112 | 2.5亿个整数中找出不重复的整数的个数,内存空间不足以容纳这2.5亿个整数。 113 | 114 | 首先,根据“内存空间不足以容纳这2.5亿个整数”我们可以快速的联想到Bit-map。下边关键的问题就是怎么设计我们的Bit-map来表示这2.5亿个数字的状态了。其实这个问题很简单,一个数字的状态只有三种,分别为不存在,只有一个,有重复。因此,我们只需要2bits就可以对一个数字的状态进行存储了,假设我们设定一个数字不存在为00,存在一次01,存在两次及其以上为11。那我们大概需要存储空间几十兆左右。 115 | 116 | 接下来的任务就是遍历一次这2.5亿个数字,如果对应的状态位为00,则将其变为01;如果对应的状态位为01,则将其变为11;如果为11,,对应的转态位保持不变。 117 | 118 | 最后,我们将状态位为01的进行统计,就得到了不重复的数字个数,时间复杂度为O(n)。 119 | 120 | 7、快速查询 121 | 122 | 同样,我们利用Bit-map也可以进行快速查询,这种情况下对于一个数字只需要一个bit位就可以了,0表示不存在,1表示存在。假设上述的题目改为,如何快速判断一个数字是够存在于上述的2.5亿个数字集合中。 123 | 124 | 同之前一样,首先我们先对所有的数字进行一次遍历,然后将相应的转态位改为1。遍历完以后就是查询,由于我们的Bit-map采取的是连续存储(整型数组形式,一个数组元素对应32bits),我们实际上是采用了一种分桶的思想。一个数组元素可以存储32个状态位,那将待查询的数字除以32,定位到对应的数组元素(桶),然后再求余(%32),就可以定位到相应的状态位。如果为1,则代表改数字存在;否则,该数字不存在。 125 | 126 | 8、布隆过滤器 127 | 128 | 当一个元素被加入集合中时,通过k个散列函数将这个元素映射成一个位数组中的k个点,并将这k个点全部置为1. 129 | 130 | 有一定的误判率--在判断一个元素是否属于某个集合时,有可能会把不属于这个集合的元素误判为属于这个集合.因此,它不适合那些"零误判"的应用场合.在能容忍低误判的应用场景下,布隆过滤器通过极少的误判换区了存储空间的极大节省. 131 | 132 | Bloom Filter使用k个相互独立的哈希函数(Hash Function),它们分别将集合中的每个元素映射到{1,…,m}的范围中。对任意一个元素x,第i个哈希函数映射的位置hi(x)就会被置为1(1≤i≤k)。注:如果一个位置多次被置为1,那么只有第一次会起作用,后面几次将没有任何效果。 133 | 134 | **在判断y是否属于这个集合时,对y应用k次哈希函数,若所有hi(y)的位置都是1(1≤i≤k),就认为y是集合中的元素,否则就认为y不是集合中的元素。** 135 | 136 | 本质上布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。 137 | 138 | 相比于传统的 List、Set、Map 等数据结构,它更高效、占用空间更少,但是缺点是其返回的结果是概率性的,而不是确切的。 -------------------------------------------------------------------------------- /数据结构/字符串排序.md: -------------------------------------------------------------------------------- 1 | # 一、低位优先(Least-Signifcant-Digit First,LSD)的字符串排序方法 2 | 3 | 这个算法要求**被排序的每个字符串长度都相等。**它会把字符串当成数字,**从字符串的右边开始向左检查字符**(相当于从数字的最低位到高位)。基数排序 4 | 5 | # 二、高位优先(MSD)的字符串排序 6 | 7 | 高位优先的字符串排序MSD可以处理不等长的字符串,它是从左向右检查每个字符,统计字符串首字母的频率,并按其来进行归类、排序,然后对归类后的字符串:将所有首字母相同的归为一个子数组,递归地分别对这些子数组排序。精炼点说就是: 8 | 9 | - 以首字母来排序,将数组切分成首字母相同的子数组 10 | - 忽略都相同的首字母,递归地排序子数组 11 | 12 | # 三、三向字符串快排序 13 | 14 | **将字符串数组切分成三个子数组:一个含有所有首字母小于切分字符的子数组,一个含有所有首字母等于切分字符的子数组,一个含有所有首字母大于切分字符的子数组。然后递归地对这三个数组排序,要注意对于所有首字母等于切分字符的子数组,在递归排序时应该忽略首字母(就像MSD中那样)。** 15 | 16 | # 四、总结 17 | 18 | ![](http://mycsdnblog.work/201919121951-j.png) 19 | 20 | -------------------------------------------------------------------------------- /数据结构/排序.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/排序.pdf -------------------------------------------------------------------------------- /数据结构/查找.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/查找.md -------------------------------------------------------------------------------- /数据结构/红黑树/BST删除.eddx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/红黑树/BST删除.eddx -------------------------------------------------------------------------------- /数据结构/红黑树/assets/1545804301946.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/红黑树/assets/1545804301946.png -------------------------------------------------------------------------------- /数据结构/红黑树/assets/1545810390091.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/红黑树/assets/1545810390091.png -------------------------------------------------------------------------------- /数据结构/红黑树/平衡二叉树的插入删除.eddx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/数据结构/红黑树/平衡二叉树的插入删除.eddx -------------------------------------------------------------------------------- /数据结构/跳表.md: -------------------------------------------------------------------------------- 1 | # 一、基本概念 2 | 3 | 对于一个单链表,即使链表是有序的,如果我们想要在其中查找某个数据,也只能从头到尾遍历链表,这样效率自然就会很低。 4 | 5 | ![](http://mycsdnblog.work/201919122211-f.png) 6 | 7 | 假如我们对链表每两个结点提取一个结点到上一级,然后建立一个索引指向原始结点,如下图所示。 8 | 9 | ![](http://mycsdnblog.work/201919122211-q.png) 10 | 11 | 这时候,我们要查找某一个数据的时候,就可以先在索引里面查找出一个大的范围,然后再下降到原始链表中精确查找。 12 | 13 | 比如,我们要查找 16,我们发现 16 位于 13 和 17 之间,这时候,我们就从 13 的地方下降到原始链表,然后再往后查询。原来我们查找 16,需要遍历 10 个结点,现在只需要遍历 7 个结点。 14 | 15 | **加一层索引后,查找一个结点需要遍历的次数减少了,也就是查找效率提高了**。 16 | 17 | 那么我们再多加一级索引呢?效果会不会有更大提升? 18 | 19 | ![](http://mycsdnblog.work/201919122214-x.png) 20 | 21 | 这一次,我们只需要遍历 6 个结点了。 22 | 23 | 数据量不大的时候这种方法可能效率提高得还不是很明显,下面看一个包含 64 个结点的例子,这次我们建立了五级索引。 24 | 25 | ![](http://mycsdnblog.work/201919122215-E.png) 26 | 27 | 查找 62 的时候原来需要遍历 62 次,现在只需要 11 次即可。**针对链表长度比较大的时候,构建索引查找效率的提升就会非常明显**。 28 | 29 | # 二、查询分析 30 | 31 | ![](http://mycsdnblog.work/201919122220-x.png) 32 | 33 | ![](http://mycsdnblog.work/201919122221-Z.png) 34 | 35 | ![](http://mycsdnblog.work/201919122222-L.png) 36 | 37 | ![](http://mycsdnblog.work/201919122223-j.png) 38 | 39 | 实际上,在实际开发中,原始链表中存储的可能是很大的对象,**而索引结点只需要存储关键值和几个指针,其额外占用的空间可以被忽略掉**。 40 | 41 | # 三、插入和删除 42 | 43 | ![](http://mycsdnblog.work/201919122224-i.png) 44 | 45 | ![](http://mycsdnblog.work/201919122225-2.png) 46 | 47 | 从链表中删除结点的时候,如果结点在索引中也有出现,那么我们除了要删除原始链表中的结点,还要删除索引中的。 48 | 49 | 当我们不停地往跳表中插入数据的时候,如果我们不更新索引,就有可能出现某两个结点之间数据非常多的情况。极端情况下,跳表还会退化为单链表。 50 | 51 | ![](http://mycsdnblog.work/201919122232-Y.png) 52 | 53 | 因此,我们需要某种手段来维护索引与原始链表大小之间的平衡,也就是说,**如果链表结点变多了,索引值就相应地增加一些**。 54 | 55 | **当我们往跳表中插入数据的时候,我们可以选择同时也将这个数据插入到部分索引层中。而插入到哪些索引层中,则由一个随机函数生成一个随机数字来决定。如果这个数字为 K,那我们就将数据插入到第一级到第 K 级索引中。** 56 | 57 | ![](http://mycsdnblog.work/201919122233-A.png) 58 | 59 | # 四、应用 60 | 61 | 为什么 Redis 要用跳表来实现有序集合而不是红黑树? 62 | 63 | Redis 中的有序集合支持的核心操作主要有以下几个: 64 | 65 | - 插入一个数据 66 | - 删除一个数据 67 | - 查找一个数据 68 | - **按照区间查找数据** 69 | - 迭代输出有序序列 70 | 71 | 其中,插入、删除、查找以及迭代输出有序序列这几个操作,红黑树也可以完成,时间复杂度和跳表是一样的。 72 | 73 | 但是,**按照区间查找数据这个操作**,红黑树的效率没有跳表高。跳表**可以在 O(logn) 时间复杂度定位区间的起点,然后在原始链表中顺序向后查询就可以了**,这样非常高效。 74 | 75 | 此外,相比于红黑树,跳表还具有代码更容易实现、可读性好、不容易出错、更加灵活等优点,因此 **Redis 用跳表来实现有序集合。** -------------------------------------------------------------------------------- /智力题/智力题.md: -------------------------------------------------------------------------------- 1 | # **1、100层楼,球可能会在某一层楼摔坏,问用2个球,最好情况下几次测试可以找出该楼层** 2 | 3 | **假设第一次扔在第x层,如果第一次没有碎,第二次的楼层就是x+x-1,第三次就是x+x-1+x-2** 4 | 5 | ![](http://mycsdnblog.work/201919242100-l.png) 6 | 7 | 假设问题存在最优解(扔鸡蛋过程),**这个解的最坏情况尝试次数是x次**,那么,我们第一次扔鸡蛋该选择哪一层? 8 | 9 | 恰恰是从第x层开始扔,选择更高一层或是更低一层都不合适 10 | 11 | 为什么第一次扔就要选择第x层呢? 12 | 13 | 这里的解释也是通过假设法,然后演绎,有些烧脑,小伙伴们坚持住: 14 | 15 | **假设第一次扔在第x+1层(比x大):** 16 | 17 | 如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔,一直扔到第x层。 18 | 19 | 这样一来,我们总共尝试了x+1次,和假设尝试x次相悖。由此可见,第一次扔的楼层必须小于x+1层。 20 | 21 | **假设第一次扔在第x-1层(比x小):** 22 | 23 | 如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔,一直扔到第x-2层。 24 | 25 | 这样一来,我们总共尝试了x-2+1 = x-1次,虽然没有超出假设次数,但似乎有些过于保守。 26 | 27 | **假设第一次扔在第x层:** 28 | 29 | 如果第一个鸡蛋碎了,那么第二个鸡蛋只能从第1层开始一层一层扔,一直扔到第x-1层。 30 | 31 | 这样一来,我们总共尝试了x-1+1 = x次,刚刚好没有超出假设次数。 32 | 33 | ------ 34 | 35 | **如果第一次扔鸡蛋没有碎,我们的尝试消耗了一次,问题就转化成了两个鸡蛋在100-x层楼往下扔,要求尝试次数不得超过x-1次** 36 | 37 | **所以第二次尝试的楼层跨度是x-1层,绝对楼层是x+(x-1)层** 38 | 39 | **同理,如果鸡蛋还没有碎,第三次楼层跨度是x-2,第四次是x-3** 40 | 41 | 最终: 42 | 43 | ``` 44 | x + (x-1) + (x-2) + ... + 1 >= 100 45 | (x+1)*x/2 >= 100 46 | ``` 47 | 48 | # **2、64匹马,8个赛道,找出跑的最快的4匹马** 49 | 50 | 第一步:全部马分为8组,每组8匹,每组各跑一次,然后淘汰掉每组的后四名,如下图(需要比赛8场) 51 | 52 | ![](http://mycsdnblog.work/201919142101-K.png) 53 | 54 | 第二步:取每组第一名进行一次比赛,然后淘汰最后四名所在组的所有马,如下图(需要比赛1场) 55 | 56 | ![](http://mycsdnblog.work/201919142102-N.png) 57 | 58 | 这个时候总冠军已经诞生,它就是A1,蓝色区域(它不需要比赛了),而其他可能跑得最快的三匹马只可能是下图中的黄色区域了(A2,A3,A4,B1,B2,B3,C1,C2,D1,共9匹马) 59 | 60 | ![](http://mycsdnblog.work/201919142103-f.png) 61 | 62 | 第三步:只要从上面的9匹马中找出跑得最快的三匹马就可以了,但是现在只要8个跑道,怎么办?那就随机选出8匹马进行一次比赛吧(需要比赛一场) 63 | 64 | 第四步:上面比赛完,选出了前三名,但是9匹马中还有一匹马没跑呢,它可能是一个潜力股啊,那就和前三名比一比吧,这四匹马比一场,选出前三名。最后加上总冠军,跑得最快的四匹马诞生了!!!(需要一场比赛) 65 | 66 | **最后,一共需要比赛的场次:8 + 1 + 1 + 1 = 11 场** -------------------------------------------------------------------------------- /计算机网络/assets/1551084094722.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551084094722.png -------------------------------------------------------------------------------- /计算机网络/assets/1551084304301.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551084304301.png -------------------------------------------------------------------------------- /计算机网络/assets/1551085355690.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551085355690.png -------------------------------------------------------------------------------- /计算机网络/assets/1551086857102.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551086857102.png -------------------------------------------------------------------------------- /计算机网络/assets/1551086868181.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551086868181.png -------------------------------------------------------------------------------- /计算机网络/assets/1551086936946.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551086936946.png -------------------------------------------------------------------------------- /计算机网络/assets/1551087273159.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551087273159.png -------------------------------------------------------------------------------- /计算机网络/assets/1551087364881.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551087364881.png -------------------------------------------------------------------------------- /计算机网络/assets/1551091402770.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551091402770.png -------------------------------------------------------------------------------- /计算机网络/assets/1551091797780.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551091797780.png -------------------------------------------------------------------------------- /计算机网络/assets/1551092022139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551092022139.png -------------------------------------------------------------------------------- /计算机网络/assets/1551093997196.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551093997196.png -------------------------------------------------------------------------------- /计算机网络/assets/1551095204273.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551095204273.png -------------------------------------------------------------------------------- /计算机网络/assets/1551096881380.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551096881380.png -------------------------------------------------------------------------------- /计算机网络/assets/1551096961208.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551096961208.png -------------------------------------------------------------------------------- /计算机网络/assets/1551098195986.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551098195986.png -------------------------------------------------------------------------------- /计算机网络/assets/1551099853175.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551099853175.png -------------------------------------------------------------------------------- /计算机网络/assets/1551100342853.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/assets/1551100342853.png -------------------------------------------------------------------------------- /计算机网络/计算机网络.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/计算机网络/计算机网络.pdf -------------------------------------------------------------------------------- /设计模式/assets/1547979569144.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1547979569144.png -------------------------------------------------------------------------------- /设计模式/assets/1548080740146.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1548080740146.png -------------------------------------------------------------------------------- /设计模式/assets/1548081632615.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1548081632615.png -------------------------------------------------------------------------------- /设计模式/assets/1548081639605.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1548081639605.png -------------------------------------------------------------------------------- /设计模式/assets/1550999701408.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1550999701408.png -------------------------------------------------------------------------------- /设计模式/assets/1551001017770.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1551001017770.png -------------------------------------------------------------------------------- /设计模式/assets/1551002538396.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1551002538396.png -------------------------------------------------------------------------------- /设计模式/assets/1551104273405.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/1551104273405.png -------------------------------------------------------------------------------- /设计模式/assets/201919141715-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/assets/201919141715-3.png -------------------------------------------------------------------------------- /设计模式/images/Package abstractfactory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package abstractfactory.png -------------------------------------------------------------------------------- /设计模式/images/Package chainofresponsibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package chainofresponsibility.png -------------------------------------------------------------------------------- /设计模式/images/Package command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package command.png -------------------------------------------------------------------------------- /设计模式/images/Package factorymethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package factorymethod.png -------------------------------------------------------------------------------- /设计模式/images/Package memento.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package memento.png -------------------------------------------------------------------------------- /设计模式/images/Package observer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package observer.png -------------------------------------------------------------------------------- /设计模式/images/Package simplefactory.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package simplefactory.png -------------------------------------------------------------------------------- /设计模式/images/Package state.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package state.png -------------------------------------------------------------------------------- /设计模式/images/Package templatemethod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Package templatemethod.png -------------------------------------------------------------------------------- /设计模式/images/Singleton.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/images/Singleton.png -------------------------------------------------------------------------------- /设计模式/新建文本文档.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/设计模式/新建文本文档.txt -------------------------------------------------------------------------------- /软件工程/软件工程.md: -------------------------------------------------------------------------------- 1 | # 一、面向对象和面向过程的区别 2 | 3 | 面向过程就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候一个一个依次调用就可以了; 4 | 5 | 面向对象是把构成问题事务分解成各个对象,建立对象的目的不是为了完成一个步骤,而是为了描叙某个事物在整个解决问题的步骤中的行为。 6 | 7 | 面向对象和面向过程最本质的区别在于考虑问题的出发点不同,面向过程是以事件流程为考虑问题的出发点,而面向对象则是以参与事件的角色为考虑问题的出发点,所以面向对象在处理问题时更加灵活。 8 | 9 | # 二、面向对象的三大特征 10 | 11 | **封装** 12 | 13 | 封装最好理解了。封装是面向对象的特征之一,是对象和类概念的主要特性。 14 | 15 | 封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏。 16 | 17 | **继承** 18 | 19 | 面向对象编程 (OOP) 语言的一个主要功能就是“继承”。继承是指这样一种能力:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 20 | 21 | 通过继承创建的新类称为“子类”或“派生类”。 22 | 23 | 被继承的类称为“基类”、“父类”或“超类”。 24 | 25 | 继承的过程,就是从一般到特殊的过程。 26 | 27 | 要实现继承,可以通过“继承”(Inheritance)和“组合”(Composition)来实现。 28 | 29 | 在某些 OOP 语言中,一个子类可以继承多个基类。但是一般情况下,一个子类只能有一个基类,要实现多重继承,可以通过多级继承来实现。 30 | 31 | 32 | 33 | 继承概念的实现方式有三类:实现继承、接口继承和可视继承。 34 | 35 | Ø 实现继承是指使用基类的属性和方法而无需额外编码的能力; 36 | 37 | Ø 接口继承是指仅使用属性和方法的名称、但是子类必须提供实现的能力; 38 | 39 | Ø 可视继承是指子窗体(类)使用基窗体(类)的外观和实现代码的能力。 40 | 41 | 在考虑使用继承时,有一点需要注意,那就是两个类之间的关系应该是“属于”关系。例如,Employee 是一个人,Manager 也是一个人,因此这两个类都可以继承 Person 类。但是 Leg 类却不能继承 Person 类,因为腿并不是一个人。 42 | 43 | 抽象类仅定义将由子类创建的一般属性和方法,创建抽象类时,请使用关键字 Interface 而不是 Class。 44 | 45 | OO开发范式大致为:划分对象→抽象类→将类组织成为层次化结构(继承和合成) →用类与实例进行设计和实现几个阶段。 46 | 47 | **多态** 48 | 49 | 多态性(polymorphisn)是允许你将父对象设置成为和一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。 50 | 51 | 实现多态,有二种方式,**覆盖,重载**。 52 | 53 | **覆盖,是指子类重新定义父类的虚函数的做法。** 54 | 55 | **重载,是指允许存在多个同名函数,而这些函数的参数表不同(或许参数个数不同,或许参数类型不同,或许两者都不同)。** 56 | 57 | 其实,重载的概念并不属于“面向对象编程”,重载的实现是:编译器根据函数不同的参数表,对同名函数的名称做修饰,然后这些同名函数就成了不同的函数(至少对于编译器来说是这样的)。如,有两个同名函数:function func(p:integer):integer;和function func(p:string):integer;。那么编译器做过修饰后的函数名称可能是这样的:int_func、str_func。对于这两个函数的调用,在编译器间就已经确定了,是静态的(记住:是静态)。也就是说,它们的地址在编译期就绑定了(早绑定),因此,重载和多态无关!真正和多态相关的是“覆盖”。当子类重新定义了父类的虚函数后,父类指针根据赋给它的不同的子类指针,动态(记住:是动态!)的调用属于子类的该函数,这样的函数调用在编译期间是无法确定的(调用的子类的虚函数的地址无法给出)。因此,这样的函数地址是在运行期绑定的(晚邦定)。结论就是:重载只是一种语言特性,与多态无关,与面向对象也无关!引用一句Bruce Eckel的话:“不要犯傻,如果它不是晚邦定,它就不是多态。” 58 | 59 | 那么,多态的作用是什么呢?我们知道,**封装可以隐藏实现细节,使得代码模块化**;**继承可以扩展已存在的代码模块(类)**;**它们的目的都是为了——代码重用**。 60 | 61 | 而多态则是为了实现另一个目的——**接口重用**!**多态的作用,就是为了类在继承和派生的时候,保证使用“家谱”中任一类的实例的某一属性时的正确调用**。 62 | 63 | # 三、软件软件开发模型 64 | 65 | ## 3.1 瀑布模型 66 | 67 | **特点:** 68 | 69 | - 阶段间具有顺序性和依赖性: 70 | - 前一阶段完成后,才能开始后一阶段 71 | - 前一阶段的输出文本为后一阶段的输入文本 72 | - 推迟实现的观点 73 | - 质量保证: 74 | - 每个阶段必须交付出合格的文档 75 | - 对文档进行审核 76 | 77 | **缺点:** 78 | 79 | - 开始需要把需求做到最全 80 | - 惧怕用户测试中的反馈,惧怕需求变更 81 | - mux 82 | 83 | ## 3.2 增量模型 84 | 85 | - 第一构件完成软件提供的基本最核心的功能 86 | - 后面的增构件是为了第一构件提供服务提供功能的 87 | - 而且避免吧难题退后,首先完成的应该是高风险和重要部分 88 | 89 | ## 3.3 螺旋模型 90 | 91 | 制定计划、风险分析、实施工程、客户评估 92 | 93 | ## 3.4 快速原型 94 | 95 | 根据用户的主要需求,建立一个软件原型,然后让用户进行评价,然后根据用户的评价和提出的更多的需求来开发出相应的软件产品 96 | 97 | -------------------------------------------------------------------------------- /需要学习/Dubbo+zookeper.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/Dubbo+zookeper.md -------------------------------------------------------------------------------- /需要学习/GraphQL.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/GraphQL.md -------------------------------------------------------------------------------- /需要学习/Java8.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/Java8.md -------------------------------------------------------------------------------- /需要学习/Netty.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/Netty.md -------------------------------------------------------------------------------- /需要学习/RxJava.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/RxJava.md -------------------------------------------------------------------------------- /需要学习/guava.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/guava.md -------------------------------------------------------------------------------- /需要学习/nginx+Lua+redis.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/nginx+Lua+redis.md -------------------------------------------------------------------------------- /需要学习/webflux.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/需要学习/webflux.md -------------------------------------------------------------------------------- /项目/JWT过期自动续期解决方案.md: -------------------------------------------------------------------------------- 1 | # 一、JWT 2 | 3 | JWT全称JSON Web Token,由三部分组成header(头部,用于描述关于该JWT的最基本的信息,例如其类型以及签名所用的算法等)、payload(载荷,就是存放有效信息的地方,在这一部分中存放过期时间)和signature(签证,签证信息)。 4 | 5 | # 二、Token过期刷新方案 6 | 7 | 1、单点登录 8 | 9 | 用户登录,后端验证用户成功之后生成两个token,这两个token分别是access_token(访问接口使用的token)、refresh_token(access_token过期后用于刷续期的token,注意设置refresh_token的过期时间需比access_token的过期时间长),后端将用户信息和这两个token存放到redis中并返回给前端。 10 | 11 | 前端在获取到登录成功返回的两个token之后,将之存放到localStorage本地存储中。 12 | 13 | 2、接口请求 14 | 前端封装统一接口请求函数、token刷新函数,在请求成功之后对返回结果进行校验,如果token过期,则调用token刷新函数请求新的token. 15 | 16 | 后端在接收到token刷新请求之后通过结合redis中存放的用户信息、token和refresh_token对请求参数进行验证,验证通过之后生成新的token和refresh_token存放到redis中并返回给前端。至此完成token刷新。 17 | 18 | 3、多请求应对 19 | 20 | 所谓多请求,就是指在短时间内同时发生多个请求,如果此时token已经过期,那么这些请求都会出现token过期请求失败的情况。 21 | 22 | 为了避免反复刷新token,需要设置一个刷新token的开关isRefresh,当一个请求出现token过期的时候,这个时候会调用token刷新函数,与此同时关闭开关将isRefresh的值设置为false,避免后续请求去调用token刷新函数。 23 | 当发现token过期时,咱们将请求延缓到token刷新之后再重新执行请求,这里采用Promise函数,把每一个token失效的请求都存到一个Promise函数集合里面,当token刷新之后打开开关将isRefresh的值设置为true,然后批量执行Promise函数集合里面的Promise函数,返回请求结果。 24 | 25 | 在后端使用RESTful APIs将应用程序迁移到HTML5时,我正在做相关的修修补补的工作。我想出的解决办法是: 26 | 27 | 1. 在成功登录后,客户端会发出会话时间为30分钟(或任何常用的服务器端会话时间)的令牌。 28 | 2. 创建一个客户端计时器来调用服务在其到期之前更新令牌。新的令牌将取代以后的调用。 29 | 30 | 如您所见,这样可以减少频繁更新令牌请求。如果用户在更新令牌调用触发之前关闭浏览器/应用程序,则先前的令牌将及时到期,用户将必须重新登录。 31 | 32 | 可以实现更复杂的策略来满足用户不活动时的情形(例如忽略打开的浏览器选项卡)。在这种情况下,续订令牌调用应包括预期到期时间,而这个时间不应超过定义的会话时间。那么应用程序必须相应地跟踪上一次用户的交互。 33 | 34 | 我不喜欢设置长期到期时间的思路,因为这种方法对于不需要那么频繁身份验证的本机应用程序可能无法正常工作。 35 | 36 | # 三、Spring Security OAuth2 37 | 38 | 主要思路: 39 | 40 | 1. 首先用过期token访问受拦截资源 41 | 2. 认证失败返回401的时候调用异常处理器 42 | 3. 通过异常处理器结合refresh_token进行token的刷新 43 | 4. 刷新成功则通过请求转发(request.getRequestDispatcher)的方式再次访问受拦截资源 44 | 45 | -------------------------------------------------------------------------------- /项目/assets/1547038556115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/项目/assets/1547038556115.png -------------------------------------------------------------------------------- /项目/assets/1551957761728.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/项目/assets/1551957761728.png -------------------------------------------------------------------------------- /项目/assets/乐优商城架构图-1551665325137.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/项目/assets/乐优商城架构图-1551665325137.png -------------------------------------------------------------------------------- /项目/assets/乐优商城架构图.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/lyj8330328/Java-Interview/f0f1c9ea17a3775f6e23b879144b47213da14031/项目/assets/乐优商城架构图.png -------------------------------------------------------------------------------- /项目/接口限流.md: -------------------------------------------------------------------------------- 1 | # 一、普通版本 2 | 3 | ```java 4 | package com.leyou.seckill.access; 5 | 6 | import java.lang.annotation.ElementType; 7 | import java.lang.annotation.Retention; 8 | import java.lang.annotation.RetentionPolicy; 9 | import java.lang.annotation.Target; 10 | 11 | /** 12 | * @Author: 98050 13 | * @Time: 2018-11-23 23:38 14 | * @Feature: 接口限流注解 15 | */ 16 | @Retention(RetentionPolicy.RUNTIME) 17 | @Target(ElementType.METHOD) 18 | public @interface AccessLimit { 19 | 20 | /** 21 | * 限流时间 22 | * @return 23 | */ 24 | int seconds(); 25 | 26 | /** 27 | * 最大请求次数 28 | * @return 29 | */ 30 | int maxCount(); 31 | 32 | /** 33 | * 是否需要登录 34 | * @return 35 | */ 36 | boolean needLogin() default true; 37 | } 38 | ``` 39 | 40 | 拦截器 41 | 42 | ```java 43 | package com.leyou.seckill.interceptor; 44 | 45 | import com.leyou.auth.entity.UserInfo; 46 | import com.leyou.response.CodeMsg; 47 | import com.leyou.response.Result; 48 | import com.leyou.seckill.access.AccessLimit; 49 | import com.leyou.utils.JsonUtils; 50 | import org.springframework.beans.factory.annotation.Autowired; 51 | import org.springframework.data.redis.core.RedisTemplate; 52 | import org.springframework.stereotype.Service; 53 | import org.springframework.web.method.HandlerMethod; 54 | import org.springframework.web.servlet.handler.HandlerInterceptorAdapter; 55 | 56 | import javax.servlet.http.HttpServletRequest; 57 | import javax.servlet.http.HttpServletResponse; 58 | import java.io.IOException; 59 | import java.io.OutputStream; 60 | import java.util.concurrent.TimeUnit; 61 | 62 | /** 63 | * @Author: 98050 64 | * @Time: 2018-11-23 23:45 65 | * @Feature: 接口限流拦截器 66 | */ 67 | @Service 68 | public class AccessInterceptor extends HandlerInterceptorAdapter { 69 | 70 | @Autowired 71 | private RedisTemplate redisTemplate; 72 | 73 | 74 | @Override 75 | public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 76 | if (handler instanceof HandlerMethod){ 77 | HandlerMethod handlerMethod = (HandlerMethod) handler; 78 | AccessLimit accessLimit = handlerMethod.getMethodAnnotation(AccessLimit.class); 79 | if (accessLimit == null){ 80 | return true; 81 | } 82 | 83 | //获取用户信息 84 | UserInfo userInfo = LoginInterceptor.getLoginUser(); 85 | int seconds = accessLimit.seconds(); 86 | int maxCount = accessLimit.maxCount(); 87 | boolean needLogin = accessLimit.needLogin(); 88 | String key = request.getRequestURI(); 89 | if (needLogin){ 90 | if (userInfo == null){ 91 | render(response, CodeMsg.LOGIN_ERROR); 92 | return false; 93 | } 94 | key += "_" + userInfo.getId(); 95 | }else { 96 | //不需要登录,则什么也不做 97 | } 98 | String count = redisTemplate.opsForValue().get(key); 99 | if (count == null){ 100 | redisTemplate.opsForValue().set(key,"1",seconds, TimeUnit.SECONDS); 101 | }else if(Integer.valueOf(count) < maxCount){ 102 | redisTemplate.opsForValue().increment(key,1); 103 | }else { 104 | render(response,CodeMsg.ACCESS_LIMIT_REACHED); 105 | } 106 | 107 | } 108 | 109 | return super.preHandle(request, response, handler); 110 | } 111 | 112 | private void render(HttpServletResponse response, CodeMsg cm) throws IOException { 113 | response.setContentType("application/json;charset=UTF-8"); 114 | OutputStream out = response.getOutputStream(); 115 | String str = JsonUtils.serialize(Result.error(cm)); 116 | out.write(str.getBytes("UTF-8")); 117 | out.flush(); 118 | out.close(); 119 | } 120 | } 121 | ``` -------------------------------------------------------------------------------- /项目/日志系统.md: -------------------------------------------------------------------------------- 1 | 日志的几大类:调试日志、业务日志、错误日志。一个软件产品上线后,都会关闭调试日志。本文的日志,重点讨论尝试以一种相对灵活的方法呈现监控和错误日志,满足技术/运维侧发现技术层面的一些问题。 2 | 3 | 以前的业务日志,主要是审计用途的,描述的内容如果用自然语言来说的话,就是:谁在什么时候、什么地方(IP等)、以什么方式(PC端、移动端、短信应答等)、对什么对象、做了一个怎样的操作、结果如何(成功还是失败)。 4 | 5 | 今天的问题已经远比以前复杂了,而且也对日志提出了更多要求,期望从日志中能够挖掘更多的信息,总结过去并能展望未来。 6 | 7 | 日志的内容: 8 | 9 | ![](http://mycsdnblog.work/201919051018-x.png) 10 | 11 | 根据这些内容,是完全可以胜任以前的那种审计工作的,但同时具备更多的信息: 12 | 13 | 1. 错误码(或者返回码,参考《接口的返回码》)可以指导这个为何出错,并能传递给各个环节均是因为这个原因出错 14 | 2. 跟踪信息,可以把分布式环境下的运行日志穿起来,看问题的来龙去脉,看系统运行的过程 15 | 3. 入参和出参和异常,分析和重现问题发生的场景 16 | 17 | 这些信息在不同的场景下输出内容不尽相同: 18 | 19 | 1. 只有错误日志或者特定调试时才需要打印入参、出参 20 | 2. 正常场景下只需要打印监控信息即可 21 | 3. 避免一个线程中的一个异常被不同的嵌入调用的过程中反复打印 22 | 23 | 日志发生的对象 24 | 25 | 我们把日志的对象分成两类,区别在于不同的对象记录日志过程中的处理方式存在较大差别,如下: 26 | 27 | ![](http://mycsdnblog.work/201919051019-y.png) 28 | 29 | 入口类的特殊性在于,他是一段日志的开始也是日志的结束,对日志的处理与过程不同。而过程类主要是记录监控日志以及错误的时候处理错误日志。 30 | 31 | 1、定义日志注解 32 | 33 | ```java 34 | @Target({ElementType.METHOD}) 35 | @Retention(RetentionPolicy.RUNTIME) 36 | @Documented 37 | @Order(Ordered.HIGHEST_PRECEDENCE) 38 | public @interface LogPoint { 39 | String businessTag(); 40 | Format format() default Format.TEXT; 41 | Level level() default Level.INFO; 42 | String[] encryptArgs() default ""; 43 | boolean isEntrance() default false; 44 | enum Format { 45 | JSON, 46 | TEXT 47 | } 48 | enum Level { 49 | ERROR, 50 | INFO 51 | } 52 | } 53 | ``` 54 | 55 | 2、定义注解拦截器 56 | 57 | ```java 58 | @Aspect 59 | public class LogRecorder { 60 | private final static DateTimeFormatter DF = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); 61 | private final static AtomicLong COUNTER = new AtomicLong(1000000); 62 | @Value("${spring.application.name}") 63 | private String applicationName; 64 | @Around("@annotation(LogPoint)") 65 | public Object log(ProceedingJoinPoint pjp) throws Throwable { 66 | final long start = System.currentTimeMillis(); 67 | final long end; 68 | final long count = COUNTER.incrementAndGet(); 69 | Throwable t = null; 70 | Object result = null; 71 | Class classTarget = pjp.getTarget().getClass(); 72 | Method currentMethod = LogUtil.getCurrentMethod(pjp); 73 | Object[] args = pjp.getArgs(); 74 | Logable log = currentMethod.getAnnotation(LogPoint.class); 75 | Logger detailLogger = LogUtil.getLogger(log.loggerName() + "-detail"); 76 | try { 77 | result = pjp.proceed(); 78 | } catch (Throwable t1) { 79 | t = t1; 80 | } finally { 81 | end = System.currentTimeMillis(); 82 | } 83 | String businessCode = "-"; 84 | If(t!= null && t instanceof AppException) { 85 | businessCode=((AppException)t).getCode(); 86 | } 87 | //已经准备好全部信息了,可以打印日志了,可以输出json或者text的日志,可以打印到文件或者放入kafka队列,或者根据不同的级别输出不同的内容 88 | if (t == null) { 89 | return result; 90 | } else { 91 | throw t; 92 | } 93 | } 94 | ``` 95 | 96 | 3、业务上使用注解 97 | 98 | ```java 99 | @LogPoint("User") 100 | Public User create(String username, String nickname){ 101 | userMapper.create(xxxx); 102 | } 103 | ``` 104 | 105 | 4、日志处理 106 | 107 | 日志生成后,可以使用flume等工具进行汇聚,进而使用Spark等大数据框架分析和挖掘,后续继续讲这些。 108 | 109 | 日志的一些应用场景 110 | 111 | 1. 追踪业务的调用过程,分析和优化不合理的地方,前些时候,我们系统发现一笔订单调用另一个系统10多次,分析发现,双方接口粒度太小,果断重构优化 112 | 2. 监控方法的执行时长,发现系统变更趋势,优化系统对受限资源的访问 113 | 3. 异常时,打印输入参数,重现异常场景 114 | 4. 监控各种异常码,并针对异常码优化,例如,某某上游失败明显增加、从某某银行的卡片发出的快捷支付失败率增加 -------------------------------------------------------------------------------- /项目/电商网站详情页系统架构.md: -------------------------------------------------------------------------------- 1 | # 一、商品详情系统架构图 2 | 3 | ## 1.1 小型网站 4 | 5 | ![](http://mycsdnblog.work/201919032008-k.png) 6 | 7 | 下面是页面模板的简单 Demo 。 8 | 9 | ``` 10 | 11 | 12 | 商品名称:#{productName}
13 | 商品价格:#{productPrice}
14 | 商品描述:#{productDesc} 15 | 16 | 17 | ``` 18 | 19 | 这样做,**好处**在于,用户每次浏览一个页面,不需要进行任何的跟数据库的交互逻辑,也不需要执行任何的代码,直接返回一个 html 页面就可以了,速度和性能非常高。 20 | 21 | 对于小网站,页面很少,很实用,非常简单,Java 中可以使用 **velocity、freemarker、thymeleaf** 等等,然后做个 cms 页面内容管理系统,模板变更的时候,点击按钮或者系统自动化重新进行全量渲染。 22 | 23 | **坏处**在于,仅仅适用于一些小型的网站,比如页面的规模在几十到几万不等。对于一些大型的电商网站,亿级数量的页面,你说你每次页面模板修改了,都需要将这么多页面全量静态化,靠谱吗?每次渲染花个好几天时间,那你整个网站就废掉了。 24 | 25 | ## 1.2 大型网站 26 | 27 | 大型电商网站商品详情页的系统设计中,当商品数据发生变更时,会将变更消息压入 MQ 消息队列中。**缓存服务**从消息队列中消费这条消息时,感知到有数据发生变更,便通过调用数据服务接口,获取变更后的数据,然后将整合好的数据推送至 redis 中。Nginx 本地缓存的数据是有一定的时间期限的,比如说 10 分钟,当数据过期之后,它就会从 redis 获取到最新的缓存数据,并且缓存到自己本地。 28 | 29 | 用户浏览网页时,动态将 Nginx 本地数据渲染到本地 html 模板并返回给用户。 30 | 31 | ![](http://mycsdnblog.work/201919032013-4.png) 32 | 33 | 虽然没有直接返回 html 页面那么快,但是因为数据在本地缓存,所以也很快,其实耗费的也就是动态渲染一个 html 页面的性能。如果 html 模板发生了变更,不需要将所有的页面重新静态化,也不需要发送请求,没有网络请求的开销,直接将数据渲染进最新的 html 页面模板后响应即可。 34 | 35 | **在这种架构下,我们需要保证系统的高可用性。** 36 | 37 | 如果系统访问量很高,Nginx 本地缓存过期失效了,redis 中的缓存也被 LRU 算法给清理掉了,那么会有较高的访问量,从缓存服务调用商品服务。但如果此时商品服务的接口发生故障,调用出现了延时,缓存服务全部的线程都被这个调用商品服务接口给耗尽了,每个线程去调用商品服务接口的时候,都会卡住很长时间,后面大量的请求过来都会卡在那儿,此时缓存服务没有足够的线程去调用其它一些服务的接口,从而导致整个大量的商品详情页无法正常显示。 38 | 39 | 这其实就是一个商品接口服务故障导致缓存服务资源耗尽的现象。 -------------------------------------------------------------------------------- /项目/秒杀系统“减库存”设计思路.md: -------------------------------------------------------------------------------- 1 | # 一、减库存的方式 2 | 3 | 在正常的电商平台购物场景中,用户的实际购买过程一般分为两步:下单和付款。你想买一台iPhone手机,在商品页面点了“立即购买”按钮,核对信息之后点击“提交订单”,这一步称为下单操作。下单之后,你只有真正完成付款操作才能算真正购买,也就是俗话说的“落袋为安”。 4 | 5 | 那如果你是架构师,你会在哪个环节完成减库存的操作呢?总结来说,减库存操作一般有如下几个方式: 6 | 7 | **下单减库存**,即当买家下单后,在商品的总库存中减去买家购买数量。下单减库存是最简单的减库存方式,也是控制最精确的一种,下单时直接通过数据库的事务机制控制商品库存,这样一定不会出现超卖的情况。但是你要知道,有些人下完单可能并不会付款。 8 | 9 | **付款减库存**,即买家下单后,并不立即减库存,而是等到有用户付款后才真正减库存,否则库存一直保留给其他买家。但因为付款时才减库存,如果并发比较高,有可能出现买家下单后付不了款的情况,因为可能商品已经被其他人买走了。 10 | 11 | **预扣库存**,这种方式相对复杂一些,买家下单后,库存为其保留一定的时间(如10分钟),超过这个时间,库存将会自动释放,释放后其他买家就可以继续购买。在买家付款前,系统会校验该订单的库存是否还有保留:如果没有保留,则再次尝试预扣;如果库存不足(也就是预扣失败)则不允许继续付款;如果预扣成功,则完成付款并实际地减去库存。 12 | 13 | 14 | 15 | 16 | 17 | Redis中维护两张表,库存表和用户下单表 18 | 19 | 请求到达后进行库存预减,预减成功后将用户id放入下单表中,当用户进行支付的时候先去下单表中查询,可以查到的话就往消息队列中发送下单消息,并且把用户id从下单表中删除。每隔30分钟进行扫库,扫订单表,进行库存回仓操作重新设置redis里面的库存!!!! -------------------------------------------------------------------------------- /项目/项目知识.md: -------------------------------------------------------------------------------- 1 | # 一、什么是服务治理 2 | 3 | 当服务越来越多,容量的评估,小服务资源浪费等问题逐渐显露,此时需要增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。 4 | 5 | # 二、什么是微服务 6 | 7 | 微:微服务的服务拆分粒度很小,例如一个用户管理就可以作为一个服务。每个服务虽小,但“五脏俱全”。 8 | 9 | # 三、服务间调用 10 | 11 | RPC:自定义数据格式,基于原生TCP通信,速度快 12 | 13 | HTTP:http其实是一种网络传输协议,基于TCP,规定了数据传输的格式。现在客户端浏览器与服务端通信基本都是采用Http协议。也可以用来进行远程服务调用。缺点是消息封装臃肿。 14 | 15 | # 四、Spring Cloud 16 | 17 | - Eureka:注册中心 18 | - Zuul:服务网关 19 | - Ribbon:负载均衡 20 | - Feign:服务调用 21 | - Hystix:熔断器 22 | 23 | # 五、Eureka 24 | 25 | Eureka就好比是滴滴,负责管理、记录服务提供者的信息。服务调用者无需自己寻找服务,而是把自己的需求告诉Eureka,然后Eureka会把符合你需求的服务告诉你。 26 | 27 | 同时,服务提供方与Eureka之间通过`“心跳”`机制进行监控,当某个服务提供方出现问题,Eureka自然会把它从服务列表中剔除。 28 | 29 | 这就实现了服务的自动注册、发现、状态监控。 30 | 31 | - Eureka:就是服务注册中心(可以是一个集群),对外暴露自己的地址 32 | - 提供者:启动后向Eureka注册自己信息(地址,提供什么服务) 33 | - 消费者:向Eureka订阅服务,Eureka会将对应服务的所有提供者地址列表发送给消费者,并且定期更新 34 | - 心跳(续约):提供者定期通过http方式向Eureka刷新自己的状态 35 | 36 | **eureka的高可用,eureka集群** 37 | 38 | 39 | 40 | # 六、Ribbon负载均衡 41 | 42 | CAP原则又称CAP定理,指的是在一个分布式系统中,Consistency(一致性)、 Availability(可用性)、Partition tolerance(分区容错性),三者不可兼得 。 43 | 44 | # 七、Hystix 45 | 46 | **所以,Ribbon的超时时间一定要小于Hystix的超时时间。** 47 | 48 | 我们使用Spring Cloud Netflix中的Eureka实现了服务注册中心以及服务注册与发现;而服务间通过Ribbon或Feign实现服务的消费以及均衡负载;通过Spring Cloud Config实现了应用多环境的外部化配置以及版本管理。为了使得服务集群更为健壮,使用Hystrix的融断机制来避免在微服务架构中个别服务出现异常时引起的故障蔓延。 49 | 50 | # 八、Elasticsearch 51 | 52 | ## 8.1 索引 53 | 54 | Elasticsearch最关键的就是提供强大的索引能力了,为了提高搜索的性能,难免会牺牲某些其他方面,比如插入/更新,否则其他数据库不用混了。往Elasticsearch里插入一条记录,其实就是直接PUT一个json的对象,这个对象有多个fields,比如name, sex, age, about, interests,那么在插入这些数据到Elasticsearch的同时,Elasticsearch还默默的为这些字段建立索引--**倒排索引**,因为Elasticsearch最核心功能是搜索。 55 | 56 | ## 8.2 Elasticsearch是如何做到快速索引的 57 | 58 | Elasticsearch使用的倒排索引比关系型数据库的B+Tree索引(为了提高查询的效率,减少磁盘寻道次数,将多个值作为一个数组通过连续区间存放,一次寻道读取多个数据,同时也降低树的高度。)快。 59 | 60 | ## 8.3 什么是倒排索引 61 | 62 | ![](http://mycsdnblog.work/201919071943-b.png) 63 | 64 | 例子: 65 | 66 | ![](http://mycsdnblog.work/201919071943-7.png) 67 | 68 | Elasticsearch建立的索引如下: 69 | 70 | ![](http://mycsdnblog.work/201919071944-t.png) 71 | 72 | > **Posting List** 73 | 74 | Elasticsearch分别为每个field都建立了一个倒排索引,Kate, John, 24, Female这些叫term,而[1,2]就是**Posting List**。Posting list就是一个int的数组,存储了所有符合某个term的文档id。 75 | 76 | 看到这里,不要认为就结束了,精彩的部分才刚开始... 77 | 78 | 通过posting list这种索引方式似乎可以很快进行查找,比如要找age=24的同学,爱回答问题的小明马上就举手回答:我知道,id是1,2的同学。但是,如果这里有上千万的记录呢?如果是想通过name来查找呢? 79 | 80 | > **Term Dictionary** 81 | 82 | Elasticsearch为了能快速找到某个term,将所有的term排个序,二分法查找term,logN的查找效率,就像通过字典查找一样,这就是**Term Dictionary**。现在再看起来,似乎和传统数据库通过B-Tree的方式类似啊,为什么说比B+Tree的查询快呢? 83 | 84 | > ##### **Term Index** 85 | > 86 | 87 | B+Tree通过减少磁盘寻道次数来提高查询性能,Elasticsearch也是采用同样的思路,直接通过内存查找term,不读磁盘,但是如果term太多,term dictionary也会很大,放内存不现实,于是有了**Term Index**,就像字典里的索引页一样,A开头的有哪些term,分别在哪页,可以理解term index是一颗树: 88 | 89 | ![](http://mycsdnblog.work/201919071946-N.png) 90 | 91 | 这棵树不会包含所有的term,它包含的是term的一些前缀。通过term index可以快速地定位到term dictionary的某个offset,然后从这个位置再往后顺序查找。 92 | 93 | ![](http://mycsdnblog.work/201919071948-n.png) 94 | 95 | 所以term index不需要存下所有的term,而仅仅是他们的一些前缀与Term Dictionary的block之间的映射关系,再结合FST(Finite State Transducers)的压缩技术,可以使term index缓存到内存中。从term index查到对应的term dictionary的block位置之后,再去磁盘上找term,大大减少了磁盘随机读的次数。 96 | 97 | # 九、令牌过期怎么办 98 | 99 | token超时刷新 100 | 101 | 对于登录的用户签发其对应的jwt,我们在jwt设置他的固定有效期时间,在有效期内用户携带jwt访问没问题,当过有效期后jwt失效,用户需要重新登录获取新的jwt。这个体验不太好,好的体验应该是:**活跃的用户应该在无感知的情况下在jwt失效后获取到新的jwt,携带这个新的jwt进行访问,而长时间不活跃的用户应该在jwt失效后需要进行重新的登录认证。** 102 | 103 | **这里就涉及到了token的超时刷新问题,解决方案看图:** 104 | 105 | ![](http://mycsdnblog.work/201919192225-a.png) 106 | 107 | - 延长`token`过期时间 108 | - 活跃用户在`token`过期时,在用户无感知的情况下动态刷新`token`,做到一直在线状态 109 | - 不活跃用户在`token`过期时,直接定向到登录页 110 | 111 | # 十、如何保证消息队列的中消息按序消费 112 | 113 | 主要思路有两种:1、单线程消费来保证消息的顺序性;2、对消息进行编号,消费者处理时根据编号判断顺序。 114 | 115 | 问题分析: 116 | 117 | ![](http://mycsdnblog.work/201919192249-H.png) 118 | 119 | 如图,data1 和 data2 是有顺序的,必须 data1 先执行,data2 后执行;这两个数据被不同的消费者消费到了,可能 data2 先执行,data1 后执行,这样原来的顺序就错乱了。 120 | 121 | 解决方案: 122 | 123 | ![](http://mycsdnblog.work/201919192250-4.png) 124 | 125 | 如图,在 MQ 里面创建多个 queue,同一规则的数据(对唯一标识进行 hash),有顺序的放入 MQ 的 queue 里面,消费者只取一个 queue 里面获取数据消费,这样执行的顺序是有序的。或者还是只有一个 queue 但是对应一个消费者,然后这个消费者内部用内存队列做排队,然后分发给底层不同的 worker 来处理。 126 | 127 | 128 | 129 | # 十一、sms短信发送失败 130 | 131 | # 十二、消息队列高可用 132 | 133 | RabbitMQ是比较有代表性的,因为是基于主从做高可用性的,我们就以他为例子讲解第一种MQ的高可用性怎么实现。(不是分布式的)rabbitmq有三种模式:单机模式,普通集群模式,镜像集群模式 134 | 135 | 普通集群 136 | 137 | 意思就是在多台机器上启动多个RabbitMQ实例,每个机器启动一个。但是你创建的queue,只会放在一个RabbitMQ实例上,但是每个实例都同步queue的元数据。完了你消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从queue所在实例上拉取数据过来。 138 | 139 | 这种方式确实很麻烦,也不怎么好,没做到所谓的分布式,就是个普通集群。因为这导致你要么消费者每次随机连接一个实例然后拉取数据,要么固定连接那个queue所在实例消费数据,前者有数据拉取的开销,后者导致单实例性能瓶颈。 140 | 141 | 而且如果那个放queue的实例宕机了,会导致接下来其他实例就无法从那个实例拉取,如果你开启了消息持久化,让RabbitMQ落地存储消息的话,消息不一定会丢,得等这个实例恢复了,然后才可以继续从这个queue拉取数据。 142 | 143 | 所以这个事儿就比较尴尬了,这就没有什么所谓的高可用性可言了,这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个queue的读写操作。 144 | 145 | 镜像集群 146 | 147 | 这种模式,才是所谓的RabbitMQ的高可用模式,跟普通集群模式不一样的是,你创建的queue,无论元数据还是queue里的消息都会存在于多个实例上,然后每次你写消息到queue的时候,都会自动把消息到多个实例的queue里进行消息同步。 148 | 149 | 这样的话,好处在于,你任何一个机器宕机了,没事儿,别的机器都可以用。坏处在于,第一,这个性能开销也太大了吧,消息同步所有机器,导致网络带宽压力和消耗很重!第二,这么玩儿,就没有扩展性可言了,如果某个queue负载很重,你加机器,新增的机器也包含了这个queue的所有数据,并没有办法线性扩展你的queue。 150 | 151 | 那么怎么开启这个镜像集群模式呢?我这里简单说一下,避免面试时人家问你你不知道,其实很简单RabbitMQ有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策略,指定的时候可以要求数据同步到所有节点的,也可以要求就同步到指定数量的节点,然后你再次创建queue的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。 152 | 153 | # 十三、jwt实现一个帐号只能同时在一个设备(端)登录的思路 154 | 155 | jwt的规范目前只检测jwt的发布者,过期时间,签名等信息.大部分现成的库都是按照标准写的.但是标准没有要求jwt带入登录时间等信息,因此用户连续登录多次,后台返回的token在有效期内都能访问后台api.也就是用户可以在多个设备同时登录. 156 | 157 | **有人会采用在登录时将jwt用redis等储存起来,在api的中间件检查时去查数据库中是否储存了这个token,设置过期时间.如果用户再次登录,那么将该token用新生成的token替代.** 158 | 159 | 我们也可以不新建一个表,因为我们多数应用的用户表中都会储存用户的最后登录时间,最后登录ip等信息,我们可以在登录时将这些信息一边储存到数据库中,一边注入到jwt中.然后在用户访问api时在中间件中从中间件取出这些信息,和用户表中的信息进行对比,如果不符合,就不允许用户访问api. 160 | 161 | --------------------------------------------------------------------------------