├── .nojekyll ├── Action ├── SpringBoot实战(1)springboot-chapters介绍.md ├── SpringBoot实战(2)helloword.md ├── SpringBoot实战(3)读取配置文件.md ├── SpringBoot实战(3)读取配置文件 │ └── 2126b210ec2.webp ├── SpringCloud实战练习(1)服务注册与发现Eureka.md ├── SpringCloud实战练习(1)服务注册与发现Eureka │ ├── 570677293649.png │ ├── 570677396266.png │ ├── 570678280491.png │ ├── 570680105311.png │ ├── 570701415543.png │ ├── 570701599343.png │ └── clipboard-1578061881346.png ├── SpringCloud实战练习(2)负载均衡Ribbon.md ├── SpringCloud实战练习(3)声明式调用Feign.md ├── SpringCloud实战练习(4)熔断监控Hystrix.md ├── SpringCloud实战练习(4)熔断监控Hystrix │ ├── clipboard-1578063450332.png │ ├── clipboard-1578063450333.png │ ├── clipboard-1578063830295.png │ └── clipboard.png ├── SpringCloud实战练习(5)路由网关Zuul.md ├── SpringCloud实战练习(5)路由网关Zuul │ └── clipboard.png ├── SpringCloud实战练习(6)配置中心Config.md └── SpringCloud实战练习(6)配置中心Config │ └── clipboard.png ├── Algo ├── 数据结构(1)总章.md ├── 数据结构(2)数组.md ├── 数据结构(3)栈.md ├── 数据结构(3)栈 │ ├── 2766054596152452712.jpg │ ├── 5165166.png │ └── chuzhan.gif ├── 数据结构(4)队列.md ├── 数据结构(4)队列 │ ├── 206967579.jpg │ ├── 345348487878.jpg │ ├── 34fasafdfsadjukjhfeqvyuERTSG.png │ ├── 5f26921094ec.jpg │ ├── uydorpvmgasnht.png │ └── wfgg31q.png ├── 数据结构(5)链表.md ├── 数据结构(5)链表 │ ├── 1120165-20171207161602113-1451349858.png │ ├── 20160420134000174.png │ ├── 2019-06-02_183101.png │ ├── 20190603-2548.png │ └── 20190603-4125512.png ├── 数据结构(6)树.md ├── 数据结构(6)树 │ ├── 20150204101904649.jpg │ ├── 2019-06-05_205958.png │ ├── 2019-06-05_211519.png │ ├── 2019-06-05_213224.png │ ├── 2019-06-05_213234.png │ ├── 2019-06-05_213755.png │ ├── 2019-06-05_214742.png │ ├── 2019-06-05_215227.png │ ├── 2019-06-05_222540.png │ ├── 2019-06-24_212644.png │ └── 9358d109b3de9c828cdb8e7c6481800a18d84382.jpg ├── 算法-基础篇(1)十大排序.md ├── 算法-基础篇(1)十大排序 │ ├── 1094457-20170225183236538-961758163.png │ ├── 140151tbt1kcsjbds6bsbd.jpg │ ├── 140152c1b40emo0c54joff.jpg │ ├── 1940317-ad940e1d1a16fc39.gif │ ├── 32qE3uY.png │ ├── 55505.jpg │ ├── 849589-20171015223238449-2146169197.gif │ ├── 849589-20171015224719590-1433219824.gif │ ├── 849589-20171015225645277-1151100000.gif │ ├── 849589-20171015230557043-37375010.gif │ ├── 849589-20171015230936371-1413523412.gif │ ├── 849589-20171015231308699-356134237.gif │ ├── 849589-20171015231740840-6968181.gif │ ├── 849589-20171015232453668-1397662527.gif │ ├── 849589-20180331170017421-364506073.gif │ ├── eaENbmi.png │ └── m6RriyQ.png ├── 算法-基础篇(2)七大查询.md └── 算法-基础篇(3)加密算法.md ├── DB ├── MySQL数据库-优化篇(1)Explain分析.md ├── MySQL数据库-优化篇(1)Explain分析 │ └── clipboard.png ├── MySQL数据库-优化篇(2)SQL优化.md ├── MySQL数据库-优化篇(2)SQL优化 │ ├── clipboard-1585471069260.png │ ├── clipboard-1585471075930.png │ ├── clipboard-1585471080641.png │ ├── clipboard-1585471104139.png │ ├── clipboard-1585471160438.png │ ├── clipboard-1585471163906.png │ ├── clipboard-1585471203419.png │ ├── clipboard-1585471209120.png │ ├── clipboard-1585471258868.png │ ├── clipboard-1585471265870.png │ ├── clipboard-1585471272332.png │ ├── clipboard-1585471286651.png │ ├── clipboard-1585471336181.png │ ├── clipboard-1585471349135.png │ ├── clipboard-1585471351583.png │ ├── clipboard-1585471370829.png │ ├── clipboard-1585471414535.png │ ├── clipboard-1585471420298.png │ ├── clipboard-1585471429052.png │ ├── clipboard-1585471433168.png │ ├── clipboard-1585471442067.png │ ├── clipboard-1585471446600.png │ ├── clipboard-1585471483435.png │ ├── clipboard-1585471487375.png │ ├── clipboard-1585471491098.png │ ├── clipboard-1585471502361.png │ ├── clipboard-1585471505672.png │ └── clipboard.png ├── MySQL数据库-基础篇(1)存储引擎.md ├── MySQL数据库-基础篇(1)存储引擎 │ └── clipboard.png ├── MySQL数据库-基础篇(2)事务与锁.md ├── MySQL数据库-基础篇(3)数据类型.md ├── MySQL数据库-基础篇(3)数据类型 │ ├── 1562926867684.png │ ├── 1562926888780.png │ └── clipboard.png ├── MySQL数据库-基础篇(4)常用函数.md ├── MySQL数据库-基础篇(4)常用函数 │ ├── clipboard-1585469653610.png │ ├── clipboard-1585469711457.png │ ├── clipboard-1585469721869.png │ ├── clipboard-1585469752042.png │ └── clipboard.png ├── MySQL数据库-基础篇(5)索引.md ├── MySQL数据库-基础篇(5)索引 │ └── clipboard.png ├── MySQL数据库-开发篇(1)设计规范.md └── MySQL数据库-开发篇(2)SQL语法.md ├── Design ├── 设计模式之简介.md ├── 设计模式(1)工厂模式.md ├── 设计模式(2)抽象工厂模式.md ├── 设计模式(3)单例模式.md ├── 设计模式(4)建造者模式.md └── 设计模式(5)原型模式.md ├── Experience ├── Mybatis中条件判断带数字的字符串.md ├── Mybatis中条件判断带数字的字符串 │ └── clipboard.png ├── 性能优化(2)MySQL模糊查询 │ ├── 1578033488870.png │ ├── 1578035852164.png │ └── 数据量大小.png ├── 性能优化(2)MySQL模糊查询优化.md └── 规范之Java命名规约.md ├── JVM ├── JVM(1)内存模型.md ├── JVM(1)内存模型 │ ├── clipboard-1578317326416.png │ ├── clipboard-1578317375718.png │ └── clipboard.png ├── JVM(2)类的加载.md ├── JVM(2)类的加载 │ ├── clipboard-1578402208674.png │ └── clipboard.png ├── JVM(3)GC回收机制.md ├── JVM(3)GC回收机制 │ ├── clipboard-1578404417512.png │ ├── clipboard-1578404442145.png │ ├── clipboard-1578404472763.png │ ├── clipboard-1578404707683.png │ └── clipboard.png └── JVM(4)GC调优.md ├── Java ├── Java-基础篇(10)泛型.md ├── Java-基础篇(1)总纲.md ├── Java-基础篇(1)总纲 │ └── Java基础.png ├── Java-基础篇(2)三大特性和六大原则.md ├── Java-基础篇(3)常用关键字特性.md ├── Java-基础篇(4)数据类型.md ├── Java-基础篇(5)类加载和初始化.md ├── Java-基础篇(6)逻辑运算.md ├── Java-基础篇(6)逻辑运算 │ └── image-20200101202719891.png ├── Java-基础篇(7)反射.md ├── Java-基础篇(8)异常.md ├── Java-基础篇(8)异常 │ └── untitled diagram.png ├── Java-基础篇(9)内部类.md ├── Java-集合篇(1)集合.md ├── Java-集合篇(1)集合 │ ├── clipboard-1578149461477.png │ ├── clipboard-1578149500539.png │ └── clipboard-1578149517475.png ├── Java-集合篇(2)集合之List.md ├── Java-集合篇(3)集合之Set.md ├── Java-集合篇(3)集合之Set │ └── clipboard-1578149491166.png ├── Java-集合篇(4)集合之Queue.md ├── Java-集合篇(5)集合之Map.md ├── Java-集合篇(5)集合之Map │ ├── clipboard-1578149421429.png │ ├── clipboard-1578149439454.png │ └── clipboard-1578149537394.png ├── 多线程(1)基础.md ├── 多线程(2)Thread.md ├── 多线程(2)Thread │ ├── clipboard.png │ └── untitled_diagram.png ├── 多线程(3)线程池.md ├── 多线程(4)线程同步.md └── 多线程(5)锁分类.md ├── Notes ├── Git 命令.md ├── Java │ ├── JDK版本特性.md │ ├── JVM.md │ ├── JavaIO.md │ ├── JavaJDBC.md │ ├── JavaNIO.md │ ├── Java基础.md │ ├── Java并发.md │ ├── Java集合.md │ └── assets │ │ ├── 1554616165.png │ │ ├── 1559390873399.png │ │ ├── 1573029522551.png │ │ ├── 1573193211462.png │ │ ├── 1573193226657.png │ │ ├── 1684165153165.png │ │ ├── 1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png │ │ ├── 2019-05-25_221513.png │ │ ├── 2019-05-25_221529-1560611871423.png │ │ ├── 2019-05-25_221529.png │ │ ├── 2019-05-25_221541.png │ │ ├── 2019-06-01_090652.png │ │ ├── 67bf5487-c45d-49b6-b9c0-a058d8c68902.png │ │ ├── 687474703a2f.jpg │ │ ├── 687474707337.jpg │ │ ├── 80804f52-8815-4096-b506-48eef3eed5c6.png │ │ ├── 952e06bd-5a65-4cab-82e4-dd1536462f38.png │ │ ├── IO.png │ │ ├── Java基础.png │ │ ├── b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png │ │ ├── clipboard-1573029104100.png │ │ ├── clipboard-1573034111430.png │ │ ├── clipboard.png │ │ ├── dfh484174.png │ │ └── overview-selectors.png ├── MongoDB │ ├── MongoDB(一)概念.md │ └── assets │ │ └── crud-annotated-document.png ├── RESTful风格.md ├── cache │ └── redis.md ├── database │ └── MySQL │ │ ├── SQL优化.md │ │ ├── SQL基础.md │ │ ├── SQL实战.md │ │ ├── assets │ │ ├── 1053629-370c020e1df96a03.webp │ │ ├── 1053629-5a796455662a3544.webp │ │ ├── 1562926867684.png │ │ ├── 1562926888780.png │ │ ├── a044ad345982b2b75818ea1c30adcbef77099b67.jpg │ │ └── c1dca4018a0b4818a52c5ab26df8fbeb.jpg │ │ └── 常用SQL脚本.sql ├── maven │ ├── Maven 基础.md │ └── assets │ │ ├── 20190921212905639.png │ │ └── 20190921212918827.png ├── spring │ ├── Mybatis原理.md │ ├── Mybatis实战.md │ ├── Shiro原理与实践.md │ ├── Spring.md │ └── assets │ │ ├── 1563093613555.png │ │ ├── 1563093796975.png │ │ ├── 1563413836956.png │ │ ├── 1563415103412.png │ │ ├── 1563415298386.png │ │ ├── 2019-06-08_113939.png │ │ ├── Realm.png │ │ ├── SessionDAO.png │ │ ├── SessionManager-1560484324202.png │ │ ├── SessionManager.png │ │ ├── ShiroArchitecture.png │ │ ├── ShiroAuthenticationSequence.png │ │ ├── ShiroAuthorizationSequence.png │ │ ├── ShiroFeatures.png │ │ ├── aop-proxy-call.png │ │ ├── e8f97e5a29a54882a3189bc5a21e8015.jpg │ │ └── mvc-context-hierarchy.png ├── springboot │ ├── SpringBoot 实战.md │ ├── assets │ │ ├── 1569492250582.png │ │ ├── 1569492566123.png │ │ └── 9770936-3d0012126b210ec2.webp │ ├── springboot 动态定时任务持久化.md │ ├── springboot(一) 简介.md │ └── springboot(二) 配置文件.md └── 面试谈话技巧.md ├── Project └── README.md ├── Question └── JavaQuestion.md ├── README.md ├── RPC ├── 分布式微服务(1)微服务架构.md └── 分布式微服务(1)微服务架构 │ ├── 1569727322900.png │ ├── 1569729288376.png │ ├── 1569743798115.png │ └── 1569744276427.png ├── Sys ├── Linux常用命令(1)文件管理命令.md └── Linux常用命令(2)文档操作.md └── Web ├── Spring(1)介绍.md ├── Spring(1)介绍 └── 2019-06-08_113939.png ├── Spring(2)IOC和DI.md ├── Spring(3)事务管理.md ├── Spring(3)事务管理 └── 1120165-20171003112557490-1092711802.png ├── Spring(4)AOP.md ├── Spring(5)MVC.md └── Spring(6)注解.md /.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/.nojekyll -------------------------------------------------------------------------------- /Action/SpringBoot实战(1)springboot-chapters介绍.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | **springboot-chapters** 是一个 SpringBoot 学习,并实战练习的项目,通过示例代码,快速简单上手教程 4 | 5 | 6 | 7 | # 模块总览 8 | 9 | **包含子模块工程如下:** 10 | 11 | ```java 12 | springboot-helloword:SpringBoot 入门工程 13 | springboot-profiles:SpringBoot 配置文件使用,分别采用 .properties和 .yml 进行配置,并进行多种方式读取 14 | springboot-web: SpringBoot Web应用简单实现 15 | springboot-aop: SpringBoot AOP 切面的实现 16 | springboot-async: SpringBoot 线程异步实现 17 | springboot-session: SpringBoot Session 运用 18 | springboot-servlet: 集成 Servlet 3.0 19 | springboot-swagger:集成 Swagger 2 进行统一 API 接口管理 20 | springboot-jpa:集成 JPA 进行数据库操作 21 | springboot-mybatis:集成 Mybatis 进行数据操作 22 | springboot-jdbc:集成 Jdbc-Tmeplate 进行数据操作 23 | springboot-mybatisplus:集成 Mybatis-plus 进行数据库操作,分页处理 24 | springboot-multi-db:多数据源 25 | springboot-dynamic-db:动态数据源运用 26 | springboot-pagehelper:集成 PageHelper 进行分页查询 27 | springboot-thymeleaf:集成 Thymeleaf 模板引擎 28 | springboot-freemarker:集成 Freemarker 模板引擎 29 | springboot-velocity:集成 Velocity 模板引擎 30 | springboot-ehcache:集成 EhCache ,进行缓存运用 31 | springboot-redis:集成 Redis ,进行缓存运用 32 | springboot-memcache:集成 memcache,进行缓存运用 33 | springboot-mongodb:集成 MongoDB,进行缓存运用 34 | springboot-shiro:集成 Shiro 进行权限认证 35 | springboot-security:集成 Spring Security 进行权限认证 36 | springboot-sso:集成 SSO 单点登录 37 | springboot-logback:集成 Logback 进行日志记录 38 | springboot-rabbitmq:集成 RabbitMQ 队列 39 | springboot-rocketmq:集成 RocketMQ 队列 40 | springboot-activemq:集成 ActiveMQ 队列 41 | springboot-kafka:集成 kafka 队列 42 | springboot-scheduld:SpringBoot 的定时器运用 43 | springboot-quartz:集成 Quartz,实现定时任务管理 44 | springboot-xxl-job:集成 xxl-Job,实现定时任务管理 45 | springboot-actuator:集成 Actuator 进行监控 46 | springboot-oauth : 集成 OAuth 2 47 | springboot-zookeeper:集成 ZooKeeper,进行分布式构建 48 | springboot-dubbo:集成 Dubbo 微服务 49 | springboot-websocket:集成 WebSocket 模块,实现后端向前端进行主动推送功能 50 | springboot-elasticsearch:集成 ElasticSearch 51 | springboot-sharding-jdbc:集成 Sharding-JDBC ,进行分库分表操作 52 | springboot-fastdfs:集成FastDFS 进行在分布式系统中进行文件上传、下载等操作 53 | springboot-devtools:集成 DevTools 模块进行热部署实现 54 | springboot-mail:集成 Mail 模块进行发送邮件 55 | ``` 56 | 57 | 58 | 59 | # 版本说明 60 | 61 | | **依赖名称(artifactId)** | **版本号** | **描述** | 62 | | ------------------------ | ------------- | ------------------------- | 63 | | spring-boot-starter | 2.2.2.RELEASE | springboot 启动类依赖 | 64 | | spring-boot-starter-web | 2.2.2.RELEASE | springboot web 启动类依赖 | 65 | 66 | 67 | 68 | # **主工程POM 文件** 69 | 70 | ```xml 71 | 72 | 74 | 4.0.0 75 | 76 | org.springframework.boot 77 | spring-boot-starter-parent 78 | 2.2.2.RELEASE 79 | 80 | 81 | com.husy 82 | springboot-chapters 83 | 1.0.0 84 | springboot-chapters 85 | pom 86 | 87 | 88 | springboot-helloword 89 | springboot-profiles 90 | springboot-web 91 | 92 | 93 | 94 | 1.8 95 | UTF-8 96 | UTF-8 97 | 98 | 99 | 100 | 101 | org.springframework.boot 102 | spring-boot-starter 103 | 104 | 105 | org.springframework.boot 106 | spring-boot-starter-test 107 | test 108 | 109 | 110 | org.junit.vintage 111 | junit-vintage-engine 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | org.springframework.boot 121 | spring-boot-maven-plugin 122 | 123 | 124 | 125 | 126 | ``` 127 | 128 | 129 | 130 | # 演练说明 131 | 132 | 子模块工程正在计划中,以下为以实现工程项目 133 | 134 | * [SpringBoot实战(1)springboot-chapters介绍](SpringBoot实战(1)springboot-chapters介绍.md) 135 | * [SpringBoot实战(2)helloword](SpringBoot实战(2)helloword.md) 136 | * [SpringBoot实战(3)读取配置文件](SpringBoot实战(3)读取配置文件.md) 137 | 138 | 139 | 140 | 141 | 142 | # 源码 143 | 144 | [开源地址]([源码实现](https://github.com/HusyCoding/springboot-chapters.git)) 145 | 146 | 147 | 148 | # 资料参考 149 | 150 | * [纯洁的微笑](http://www.ityouknow.com/spring-boot.html) -------------------------------------------------------------------------------- /Action/SpringBoot实战(2)helloword.md: -------------------------------------------------------------------------------- 1 | 这里演示如果使用 SpringBoot 写一个 hello word 2 | 3 | 在主工程项目 springboot-chapters下创建模块项目 springboot-helloword 4 | 5 | 6 | 7 | 8 | 9 | # 依赖web模块 10 | 11 | 在pom.xml中添加web支持: 12 | 13 | ```xml 14 | 15 | org.springframework.boot 16 | spring-boot-starter-web 17 | 18 | ``` 19 | 20 | 使用idea 新建项目时,pom.xml 文件中会有两个默认模块: 21 | 22 | * spring-boot-starter :核心模块,包括自动配置支持、日志和 YAML,boot-starter。 23 | * spring-boot-starter-test :测试模块,包括 JUnit、Hamcrest、Mockito。 24 | 25 | 26 | 27 | # pom文件 28 | 29 | ```xml 30 | 31 | 33 | 4.0.0 34 | 35 | com.husy 36 | springboot-chapters 37 | 1.0.0 38 | 39 | com.husy 40 | springboot-helloword 41 | 1.0.0 42 | springboot-helloword 43 | jar 44 | 45 | 46 | 47 | org.springframework.boot 48 | spring-boot-starter-web 49 | 50 | 51 | 52 | 53 | 54 | 55 | org.springframework.boot 56 | spring-boot-maven-plugin 57 | 58 | 59 | 60 | 61 | 62 | ``` 63 | 64 | 65 | 66 | 67 | 68 | # 编写 Controller 内容 69 | 70 | ```java 71 | @RestController 72 | public class HelloController { 73 | @RequestMapping("hello") 74 | public String hello(){ 75 | return "Hello World"; 76 | } 77 | } 78 | ``` 79 | 80 | 我们通过`@RestController` 源码就会知道 `@RestController` 就是 `@Controller` + `@ResponseBody`; 81 | 82 | `@RestController` 源码如下: 83 | 84 | ```java 85 | @Target({ElementType.TYPE}) 86 | @Retention(RetentionPolicy.RUNTIME) 87 | @Documented 88 | @Controller 89 | @ResponseBody 90 | public @interface RestController { 91 | @AliasFor( 92 | annotation = Controller.class 93 | ) 94 | String value() default ""; 95 | } 96 | ``` 97 | 98 | # 测试 99 | 100 | **Main** 101 | 102 | ```java 103 | @SpringBootApplication 104 | public class SpringbootHellowordApplication { 105 | 106 | public static void main(String[] args) { 107 | SpringApplication.run(SpringbootHellowordApplication.class, args); 108 | } 109 | } 110 | ``` 111 | 112 | @SpringBootApplication启用这三个功能,如:自动配置,组件扫描,并能够在其“应用程序类”上定义额外的配置 113 | 114 | 通过源码我们可以发现,@SpringBootApplication继承了如下 3 个注解 115 | 116 | * @EnableAutoConfiguration:启用Spring Boot的自动配置机制 117 | * @ComponentScan:启用@Component对应用程序所在的软件包的扫描(请参阅最佳实践) 118 | * @Configuration:允许在上下文中注册额外的bean或导入其他配置类 119 | 120 | 启动项目: 121 | 122 | 除了使用工具,如IDEA 启动,还可以使用jar启动 123 | 124 | > java -jar target / springboot-helloword-1.0.0.jar 125 | 126 | 127 | 128 | 浏览器访问 http://localhost:8080/hello ,页面显示如下: 129 | 130 | > Hello World 131 | 132 | 133 | 134 | # 开发人员工具 135 | 136 | Spring Boot包含一组额外的工具,这些工具可以使应用程序开发体验更加愉快。集成spring-boot-devtools后,只要类路径上的文件发生更改,使用的应用程序就会自动重新启动。 137 | 138 | 要想devtools支持,需添加如下依赖 139 | 140 | ```xml 141 | 142 | 143 | org.springframework.boot 144 | spring-boot-devtools 145 | true 146 | 147 | 148 | ``` 149 | 150 | 151 | 152 | [源码实现](https://github.com/HusyCoding/springboot-chapters.git) -------------------------------------------------------------------------------- /Action/SpringBoot实战(3)读取配置文件.md: -------------------------------------------------------------------------------- 1 | SpringBoot 的核心文件为 application.properties,又可以命名为application.yml,所有的与springboot集成框架等的配置属性都可以在它里面配置。 2 | 3 | 在主工程项目 springboot-chapters下创建模块项目 springboot-profiles 4 | 5 | 6 | 7 | # 演练 8 | 9 | 在主工程项目 springboot-chapters下创建模块项目 springboot-profiles 10 | 11 | ## **pom** 12 | 13 | ```xml 14 | 15 | 17 | 4.0.0 18 | 19 | com.husy 20 | springboot-chapters 21 | 1.0.0 22 | 23 | com.husy 24 | springboot-profiles 25 | 1.0.0 26 | springboot-profiles 27 | 28 | 29 | 30 | 31 | org.springframework.boot 32 | spring-boot-maven-plugin 33 | 34 | 35 | 36 | 37 | 38 | ``` 39 | 40 | 41 | 42 | ## **配置文件风格** 43 | 44 | Spring Boot 支持 2 种配置方式,properties 和 yml 文件风格,默认使用properties ,以下选一种即可 45 | 46 | **application.properties风格** 47 | 48 | ```properties 49 | my.name=战三 50 | my.sex=F 51 | my.age=18 52 | ``` 53 | 54 | **application.yml风格** 55 | 56 | ```yml 57 | my: 58 | name: 战三 59 | sex: F 60 | age: 18 61 | ``` 62 | 63 | 64 | 65 | # 获取配置文件方式 66 | 67 | * 通过 `@Value`注解取值 68 | 69 | * 通过Environment取值 70 | 71 | * 通过将配置文件装配到实体类 72 | 73 | 74 | 75 | ## **@Value 取值** 76 | 77 | ```java 78 | @SpringBootTest 79 | class SpringbootProfilesApplicationTests { 80 | @Value("${my.name}") 81 | String name; 82 | String sqldb; 83 | @Value("${my.sex}") 84 | String sex; 85 | @Value("${my.age}") 86 | Integer age; 87 | 88 | @Test 89 | void contextLoads() { 90 | System.out.println(name); 91 | System.out.println(sex); 92 | System.out.println(age); 93 | } 94 | 95 | } 96 | ``` 97 | 98 | **properties取值乱码问题** 99 | 100 | 注意,当我们从 application.properties 获取中文是,可能发生乱码, 101 | 102 | **解决方案:** 103 | 104 | 1、IntelliJ IDEA 开发工具如下: 105 | 106 | > 设置 File Encodings的Transparent native-to-ascii conversion为true,具体步骤如下:依次点击 107 | > 108 | > File -> Settings -> Editor -> File Encodings 109 | > 110 | > 将Properties Files (*.properties)下的Default encoding for properties files设置为UTF-8,将Transparent native-to-ascii conversion前的勾选上。 111 | > 112 | > 配置完成后一定要重新新建一个application.properties 113 | 114 | 2、在yml文件中进行配置,不会发生乱码 115 | 116 | 117 | 118 | **@Value注解失效问题** 119 | 120 | 该方式有个不好的地方,就是在使用时,需要注意@Value注解是否生效的问题。一般使用有以下注意事项 121 | 122 | * 不能作用于静态变量(static) 123 | * 不能作用于常量(final) 124 | * 不能在非注册的类中使用(类需要被注册在spring上下文中,如用@Service,@RestController,@Component等) 125 | * 使用这个类时,只能通过依赖注入的方式,用new的方式是不会自动注入这些配置的 126 | 127 | 为什么呢? 我们可以通过Spring在初始化Bean的过程了解 128 | 129 | ![img](SpringBoot实战(3)读取配置文件/2126b210ec2.webp) 130 | 131 | 解释一下: 132 | 133 | 1. 读取定义 134 | 2. Bean Factory Post Processing 135 | 3. 实例化 136 | 4. 属性注入 137 | 5. Bean Post Processing 138 | 139 | 这个问题的原因就很明显了。@Value注入是在第四步,而初始化变量是在第三部,这个使用变量还没有被注入,自然为null了。 140 | 141 | 142 | 143 | ## **Environment取值** 144 | 145 | org.springframework.core.env.Environment是当前应用运行环境的公开接口,主要包括应用程序运行环境的两个关键方面:配置文件(profiles)和属性。Environment继承自接口PropertyResolver,而PropertyResolver提供了属性访问的相关方法。 146 | 147 | 代码实现如下: 148 | 149 | ```java 150 | @Autowired 151 | private Environment environment; 152 | @Test 153 | void contextLoads2() { 154 | System.out.println(environment.getProperty("my.name")); 155 | System.out.println(environment.getProperty("my.sex")); 156 | System.out.println(environment.getProperty("my.age")); 157 | } 158 | ``` 159 | 160 | 161 | 162 | **配置文件装配到实体类** 163 | 164 | 当有读取很多配置属性时,如果逐个读取属性会非常麻烦,通常会把这些属性作为一个变量名来创建一个JavaBean 的变量 165 | 166 | 可通过注解@ConfigurationProperties获取配置文件中的指定值并注入到实体类中 167 | 168 | 169 | 170 | **代码实现:** 171 | 172 | 配置类: 173 | 174 | ```java 175 | @Component 176 | @ConfigurationProperties(prefix = "my") 177 | public class ConfigBean { 178 | String name; 179 | String sex; 180 | Integer age; 181 | 182 | // 省略getter,setter,toString方法 183 | } 184 | ``` 185 | 186 | 测试 187 | 188 | ```java 189 | @Autowired 190 | ConfigBean configBean; 191 | 192 | @Test 193 | void contextLoads3() { 194 | System.out.println(configBean.getName()); 195 | System.out.println(configBean.getSex()); 196 | System.out.println(configBean.getAge()); 197 | } 198 | ``` 199 | 200 | 201 | 202 | # **读取自定义文件** 203 | 204 | 我们可以通过@PropertySource指定读取的配置文件,如下: 205 | 206 | 在实际开发过程中,可能有多个不同的环境配置文件,Spring Boot 支持启动时在配置文件application.yml中指定环境的配置环境,配置文件格式为application-{profile}.properties,其中{profile}对应环境标识, 207 | 208 | 例如: 209 | 210 | > application-test.properties 测试环境 211 | > application-dev.properties 开发环境 212 | > application-prod.properties 生产环境 213 | 214 | 如何指定使用哪个环境配置文件,只需要配置上 spring.Profiles.active,该配置标识系统将采用哪个profiles。 215 | 216 | 如下: 217 | 218 | ```properties 219 | spring.profiles.acitve=dev 220 | ``` 221 | 222 | 当然我们也可以通过 java -jar 这种方式启动程序,并指定程序的配置文件,启动命令如下: 223 | 224 | > java -jar springboot-profiles-1.0.0.jar --spring.profiles.acitve=dev 225 | 226 | 227 | 228 | 229 | 230 | [源码实现](https://github.com/HusyCoding/springboot-chapters.git) -------------------------------------------------------------------------------- /Action/SpringBoot实战(3)读取配置文件/2126b210ec2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringBoot实战(3)读取配置文件/2126b210ec2.webp -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570677293649.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570677293649.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570677396266.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570677396266.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570678280491.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570678280491.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570680105311.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570680105311.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570701415543.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570701415543.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/570701599343.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/570701599343.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(1)服务注册与发现Eureka/clipboard-1578061881346.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(1)服务注册与发现Eureka/clipboard-1578061881346.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(2)负载均衡Ribbon.md: -------------------------------------------------------------------------------- 1 | ## 案例实践 2 | 3 | 在springcloud-chapters 项目中新建module工程 eureka-client-ribbon ,其作为服务消费者,通过 RestTemplate 来远程调用 eureka-client 服务 API 接口的“/hi”,即消费服务。该工程需要引用依赖spring-cloud-starter-netflix-ribbon 和 spring-boot-starter-web 依赖 4 | 5 | **pom 文件** 6 | 7 | ```xml 8 | 9 | 11 | 4.0.0 12 | 13 | com.husy 14 | springcloud-chapters 15 | 1.0-SNAPSHOT 16 | 17 | com.husy 18 | eureka-client-ribbon 19 | 0.0.1-SNAPSHOT 20 | eureka-client-ribbon 21 | 负载均衡客户端 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-starter-netflix-ribbon 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-starter-netflix-eureka-client 35 | 36 | 37 | 38 | 39 | 40 | 41 | org.springframework.boot 42 | spring-boot-maven-plugin 43 | 44 | 45 | 46 | 47 | 48 | ``` 49 | 50 | **yml文件** 51 | 52 | ```yml 53 | server: 54 | port: 8201 55 | spring: 56 | application: 57 | name: eureka-ribbon-client 58 | eureka: 59 | client: 60 | service-url: 61 | defaultZone: http://localhost:8001/eureka/ 62 | ``` 63 | 64 | **启动类** 65 | 66 | ```java 67 | @EnableEurekaClient 68 | @SpringBootApplication 69 | public class EurekaClientRibbonApplication { 70 | public static void main(String[] args) { 71 | SpringApplication.run(EurekaClientRibbonApplication.class, args); 72 | } 73 | } 74 | ``` 75 | 76 | **控制器与服务层** 77 | 78 | ```java 79 | @RestController 80 | public class RibbonController { 81 | @Autowired 82 | LoadBalancerClient loadBalancerClient; 83 | @Autowired 84 | private RibbonService ribbonService; 85 | 86 | @GetMapping("/hi") 87 | public String hi(@RequestParam(required = false, defaultValue = "husy") String name) { 88 | return ribbonService.hi(name); 89 | } 90 | 91 | @GetMapping("/testInstance") 92 | public String testInstance() { 93 | ServiceInstance serviceInstance = this.loadBalancerClient.choose("eureka-client"); 94 | // 打印当前选择的是哪个节点 95 | return "节点打印-->>"+ serviceInstance.getServiceId()+":"+ serviceInstance.getHost()+":"+ serviceInstance.getPort(); 96 | } 97 | } 98 | ``` 99 | 100 | ```java 101 | public interface RibbonService { 102 | String hi(String name); 103 | } 104 | 105 | @Service 106 | public class RibbonServiceImpl implements RibbonService { 107 | @Autowired 108 | RestTemplate restTemplate; 109 | 110 | @Override 111 | @GetMapping("/hi") 112 | public String hi(@RequestParam(required = false, defaultValue = "husy") String name) { 113 | return restTemplate.getForObject("http://eureka-client/hi?name=" + name, String.class); 114 | } 115 | } 116 | ``` 117 | 118 | 119 | 120 | **启动测试** 121 | 122 | 启动 eureka-cluster-server(或者eureka-server) 服务器,再启用eureka-cluster-client 服务提供者,然后在启动 eureka-client-ribbon 服务消费者。 123 | 124 | 多次访问浏览器 http://localhost:8201/hi?name=aaa ,浏览器会轮流显示如下内容: 125 | 126 | > hi aaa,i am form port:8101 127 | > 128 | > hi aaa,i am form port:8102 129 | 130 | 多次访问浏览器 http://localhost:8201/testInstance ,浏览器会轮流显示如下内容: 131 | 132 | > 节点打印-->>eureka-client:localhost:8101 133 | > 134 | > 节点打印-->>eureka-client:localhost:8102 135 | 136 | 137 | 138 | **这说明负载均衡器起了作用,负载均衡器会轮流地请求eureka-cluster-client 两个实例中的“ API 接口。** -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(3)声明式调用Feign.md: -------------------------------------------------------------------------------- 1 | # 案例实践 2 | 3 | 创建module工程 eureka-client-feign 4 | 5 | **pom文件** 6 | 7 | ```xml 8 | 9 | 11 | 4.0.0 12 | 13 | com.husy 14 | springcloud-chapters 15 | 1.0-SNAPSHOT 16 | 17 | com.husy 18 | eureka-client-feign 19 | 0.0.1-SNAPSHOT 20 | eureka-client-feign 21 | feign 服务消费者 22 | 23 | 24 | 25 | org.springframework.boot 26 | spring-boot-starter-web 27 | 28 | 29 | org.springframework.cloud 30 | spring-cloud-starter-openfeign 31 | 32 | 33 | org.springframework.cloud 34 | spring-cloud-starter-netflix-eureka-client 35 | 36 | 37 | 38 | 39 | 40 | org.springframework.boot 41 | spring-boot-maven-plugin 42 | 43 | 44 | 45 | 46 | ``` 47 | 48 | **yml 文件** 49 | 50 | ```yml 51 | spring: 52 | application: 53 | name: eureka-client-feign 54 | server: 55 | port: 8202 56 | eureka: 57 | client: 58 | service-url: 59 | defaultZone: http://localhost:8001/eureka 60 | ``` 61 | 62 | **启动类** 63 | 64 | ```java 65 | @EnableEurekaClient 66 | @EnableFeignClients 67 | @SpringBootApplication 68 | public class EurekaClientFeignApplication { 69 | public static void main(String[] args) { 70 | SpringApplication.run(EurekaClientFeignApplication.class, args); 71 | } 72 | } 73 | ``` 74 | 75 | **Feign Client 配置类** 76 | 77 | ```java 78 | @Configuration 79 | public class FeignConfig { 80 | @Bean 81 | public Retryer feignRertyer() { 82 | return new Retryer.Default(100, TimeUnit.SECONDS.toMillis(1), 5); 83 | } 84 | } 85 | ``` 86 | 87 | **控制层/业务层** 88 | 89 | ```java 90 | /** 91 | * @description: 业务接口 92 | */ 93 | public interface HiService { 94 | String sayHi(String name ); 95 | } 96 | 97 | /** 98 | * @description: 业务实现 99 | */ 100 | @Service 101 | public class HiServiceImpl implements HiService { 102 | @Resource 103 | EurekaClientFeign eurekaClientFeign; 104 | 105 | @Override 106 | public String sayHi(String name) { 107 | return eurekaClientFeign.sayHi(name); 108 | } 109 | } 110 | /** 111 | * @description: 控制器 112 | */ 113 | @RestController 114 | public class HiController { 115 | @Autowired 116 | HiService hiService; 117 | 118 | @GetMapping("/hi") 119 | public String sayHi(@RequestParam(defaultValue = "husy",required = false)String name ){ 120 | return hiService.sayHi(name); 121 | } 122 | } 123 | ``` 124 | 125 | **启动测试** 126 | 127 | 这里我们启动eureka-server 工程,端口号为8001,在启动两个 eureka-cluster-client-producer 工程,端口分表8101和8102。在启动eureka-client-feign 工程,端口号为8202 128 | 129 | 在浏览器上多次访问http://localhost:8202/hi?name=aaa ,浏览器会轮流显示以下内容: 130 | 131 | > hi aaa,i am form port:8101 132 | > 133 | > hi aaa,i am form port:8102 134 | 135 | 136 | 137 | 为什么会出现负载均衡的效果呢? 138 | 139 | 我们查看 spring-cloud-starter-openfeign 依赖,发现其有 spring-cloud-starter-netflix-ribbon 依赖和 feign-hystrix 依赖 -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063450332.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063450332.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063450333.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063450333.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063830295.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard-1578063830295.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(4)熔断监控Hystrix/clipboard.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(5)路由网关Zuul/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(5)路由网关Zuul/clipboard.png -------------------------------------------------------------------------------- /Action/SpringCloud实战练习(6)配置中心Config/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Action/SpringCloud实战练习(6)配置中心Config/clipboard.png -------------------------------------------------------------------------------- /Algo/数据结构(1)总章.md: -------------------------------------------------------------------------------- 1 | 在所有数据结构中,我们可以按逻辑结构、存储方式、数据类型等进行划分 2 | 3 | **逻辑结构可分:** 4 | 5 | * 集合:数据结构中的元素之间除了“同属一个集合” 的相互关系外,别无其他关系; 6 | * 线性结构:数据结构中的元素存在一对一的相互关系;包含:数组、栈、队列、链表、散列表 7 | * 树形结构:数据结构中的元素存在一对多的相互关系; 8 | * 图形结构:数据结构中的元素存在多对多的相互关系。 9 | 10 | 11 | 12 | **常见的存储结构有:** 13 | 14 | * 顺序存储 15 | * 链式存储 16 | * 索引存储 17 | * 散列存储 18 | 19 | 20 | 21 | **八大数据类型:** 22 | 23 | * 数组 24 | * 栈 25 | * 队列 26 | * 链表 27 | * 树 28 | * 图 29 | * 堆 30 | * 散列表 31 | 32 | 33 | 34 | 35 | 36 | **资料参考** 37 | 38 | * 算法:第4版 39 | * 数据结构与算法分析(Java版) 40 | * [队列详解及java实现](https://www.cnblogs.com/fzz9/p/8159679.html) 41 | * [从B树、B+树、B*树谈到R 树]( -------------------------------------------------------------------------------- /Algo/数据结构(2)数组.md: -------------------------------------------------------------------------------- 1 | # 定义 2 | 3 | 数组在内存中的分配是连续的,元素存储也是连续的。通过数组下标进行访问 4 | 5 | **优点:**有索引存储,所以访问速度快 6 | 7 | **缺点:** 8 | 9 | * 数组大小固定,无法扩容 10 | 11 | * 数组只能存储一种数据类型 12 | 13 | * 数组新增、删除会对整个数组进行复制操作,所以速度慢 14 | 15 | 16 | 17 | **代码示例**: 18 | 19 | ```java 20 | // 声明并创建一个数组: 21 | int[] a = new int[N] 22 | // 初始化一个输出 23 | a[i] = 1; 24 | 25 | // 简写: 26 | int[] a = {1,2,3,4,5,6} 27 | 28 | int[] b = a ; // 这只是引用地址的复制 29 | b[2] = 100; // a[2] 的值也会变成 100 30 | ``` 31 | 32 | 33 | 34 | # 常见处理 35 | 36 | ## 找出数组中最大值 37 | 38 | ```java 39 | int[] a = {1,2,3,4,5,6}; 40 | int max = a[0]; 41 | for (int i : a){ 42 | if (i > max){ 43 | max = i; 44 | } 45 | } 46 | System.out.println(max); 47 | ``` 48 | 49 | 50 | 51 | ## 计算数组元素平均值 52 | 53 | ```java 54 | int[] a = {1,2,3,4,5,6}; 55 | int sum = 0 ; 56 | for (int i : a){ 57 | sum += i; 58 | } 59 | System.out.println(sum); 60 | ``` 61 | 62 | 63 | 64 | ## 复制数组 65 | 66 | ```java 67 | int[] a = { 1, 2, 3, 4, 5, 6 }; 68 | 69 | int[] b = new int[a.length]; 70 | for (int i = 0; i < a.length; i++) { 71 | b[i] = a[i]; 72 | } 73 | 74 | // 或者 75 | System.arraycopy(a, 0, b, 0, a.length); 76 | ``` 77 | 78 | 79 | 80 | ## 颠倒数组 81 | 82 | ```java 83 | int[] a = { 1, 2, 3, 4, 5, 6 }; 84 | 85 | int n = a.length; 86 | for (int i = 0; i < n/2; i++) { 87 | int temp = a[i]; 88 | a[i] = a[n-1-i]; 89 | a[n-1-i] = temp; 90 | } 91 | System.out.println(Arrays.toString(a)); 92 | ``` 93 | 94 | 95 | 96 | # 矩阵 97 | 98 | 对称矩阵、三角矩阵 99 | 100 | -------------------(正在建设中,敬请期待!!!!) 101 | 102 | 103 | 104 | -------------------------------------------------------------------------------- /Algo/数据结构(3)栈.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 栈是一种特殊的线性表,仅能在表的一端进行插入和删除操作,通常操作的一端为栈顶(Top),另一端为栈底(Bottom)。当top= -1时为空栈,top=0表示栈中只有一个元素 6 | 7 | 栈的特点是:**先进后出,或者说是后进先出**,简称“LIFO” 8 | 9 | 当栈满时进栈称为 “上溢”;当栈空时退栈称为 “下溢”, 10 | 11 | 堆栈的存储结构有 顺序存储结构 和 链式存储结构 ,在顺序结构下需要考虑 “上溢”;在链式存储结构下不需要考虑 “上溢”,只需要考虑 “下溢” 12 | 13 | 堆栈溢出一般是循环的递归调用、大数据结构的局部变量导致的 14 | 15 | ![](./数据结构(3)栈/5165166.png) 16 | 17 | 我们以手枪弹夹为例,是不是很经典!!!! 18 | 19 |
20 | 21 | 22 |
23 | 24 | 25 | 26 | **Stack** 27 | 28 | 我们之前学过了集合,知道 Vector 集合有个子类 Stack 堆栈, 29 | 30 | 所以 Stack 继承了Vector 的特性,**也是线程安全;** 31 | 32 | ```java 33 | public class Stack extends Vector { 34 | public E push(E item) { // 将元素推送到此堆栈的顶部。 35 | addElement(item); // 该方法已经是线程安全的了 36 | return item; 37 | } 38 | public synchronized E pop() { // 删除此堆栈顶部的对象,并将该对象作为此函数的值返回。 39 | E obj; 40 | int len = size(); 41 | obj = peek(); 42 | removeElementAt(len - 1); 43 | return obj; 44 | } 45 | public synchronized E peek() { //查看此堆栈顶部的对象,而不从堆栈中删除它。 46 | int len = size(); 47 | if (len == 0) throw new EmptyStackException(); 48 | return elementAt(len - 1); 49 | } 50 | public boolean empty() { // 测试此堆栈是否为空。 51 | return size() == 0; 52 | } 53 | public synchronized int search(Object o) { // 返回一个对象在此堆栈上的基于1的位置。 54 | int i = lastIndexOf(o); 55 | if (i >= 0) return size() - i; 56 | return -1; 57 | } 58 | } 59 | ``` 60 | 61 | -------------------------------------------------------------------------------- /Algo/数据结构(3)栈/2766054596152452712.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(3)栈/2766054596152452712.jpg -------------------------------------------------------------------------------- /Algo/数据结构(3)栈/5165166.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(3)栈/5165166.png -------------------------------------------------------------------------------- /Algo/数据结构(3)栈/chuzhan.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(3)栈/chuzhan.gif -------------------------------------------------------------------------------- /Algo/数据结构(4)队列.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | # 队列特性 8 | 9 | ![](./数据结构(4)队列//206967579.jpg) 10 | 11 | 队列和栈相似,是另一种顺序存储元素的线性数据结构。 12 | 13 | * **有两个指针 front、rear指向对头 和队尾;** 14 | 15 | * 队头(front)一端进行删除操作,队尾(rear)一端进行插入操作,**是FIFO,即先进先出** 16 | 17 | * 使用场景:因为队列先进先出的特点,在多线程阻塞队列管理中非常适用。 18 | 19 | * 栈与队列的区别:最大差别在于**栈是LIFO(后进先出)** 20 | 21 | * 队列分:顺序队列 、循环队列、链式队列 22 | 23 | ![](./数据结构(4)队列//345348487878.jpg) 24 | 25 | 26 | 27 | 28 | 29 | # 顺序队列 30 | 31 | ## 顺序对象过程 32 | 33 | ![](./数据结构(4)队列//5f26921094ec.jpg) 34 | 35 | 队列过程: 36 | 37 | * 队头和队尾的指针在初始化是都为指向 0 38 | * 当插入一个元素时,rear 加 1; 39 | * 当删除一个元素时,front 减 1; 40 | 41 | **由此可见:当 front = rear 时,队列为空。** 42 | 43 | 44 | 45 | 46 | 47 | ## 假溢出现象 48 | 49 | 当队列经过新增,有经过删除时。即此时 front = rear 时,队列为空;但是在添加元素时,可能会发生 **“假溢出” 现象**,如图:![](./数据结构(4)队列//uydorpvmgasnht.png) 50 | 51 | 假溢出现象解决方案: 52 | 53 | 1. 使用一个计数器记录队列中元素个数(即队列长度) 54 | 2. 使用循环队列,人为浪费一个单元,令队满特征为 front = (rear +1)%maxSize 55 | 56 | ![](./数据结构(4)队列//34fasafdfsadjukjhfeqvyuERTSG.png) 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | # 循环队列 65 | 66 | **循环队列是改进版的顺序队列,没有“假溢出”现象** 67 | 68 | **在顺序队列中,当rear=front的时候,队列可能是满,也可能是空。** 69 | 70 | 因此循环队列,加入了对 满和空两种情况的判断: 71 | 72 | * **队满**:添加元素时,rear + 1 指向了 head 的元素。也就是转圈子要碰头了,就认为队列满了。即:**front (rear+1)%MAXSIZE** 73 | 74 | * **队空**:删除元素到 head = rear 的时候,我们认为队列空了。**rear == front,不一定为0** 75 | 76 | 77 | 78 | **Java 循环实现** 79 | 80 | ```java 81 | public class ArrayQueue { 82 | Object[] elementData; // 对象数组,队列最多存储a.length-1个对象 83 | int front; // 队首下标 84 | int rear; // 队尾下标 85 | 86 | public ArrayQueue() { 87 | this(10); // 调用其他构造方法 88 | } 89 | 90 | public ArrayQueue(int size) { 91 | elementData = new Object[size]; 92 | front = 0; 93 | rear = 0; 94 | } 95 | 96 | // 入队 97 | public boolean push(Object obj) { 98 | if ((rear + 1) % elementData.length == front) { // 关键步骤 判断是否队满 99 | return false; 100 | } 101 | elementData[rear] = obj; 102 | rear = (rear + 1) % elementData.length; // 关键步骤 队尾指针后移 103 | return true; 104 | } 105 | 106 | // 出队 107 | public Object pop() { 108 | if (rear == front) { // 关键步骤 判断是否队空 109 | return null; 110 | } 111 | Object obj = elementData[front]; 112 | front = (front + 1) % elementData.length; // 关键步骤 队头指针后移 113 | return obj; 114 | } 115 | 116 | public static void main(String[] args) { 117 | ArrayQueue q = new ArrayQueue(4); 118 | System.out.println(q.push("张三")); // true 119 | System.out.println(q.push("李斯")); // true 120 | System.out.println(q.push("赵五")); // true 121 | System.out.println(q.push("王一")); // false 无法入队列,队列满 122 | for (int i = 0; i < 4; i++) { 123 | System.out.println(q.pop()); 124 | } 125 | /* 循环体输出 : 126 | * 张三 127 | * 李斯 128 | * 赵五 129 | * null 130 | */ 131 | } 132 | } 133 | ``` 134 | 135 | 136 | 137 | # 链式队列 138 | 139 | 链式存储结构,限制仅在表头删除和表尾插入的单链表 140 | 141 | ![](./数据结构(4)队列//wfgg31q.png) 142 | 143 | 代码实现 144 | 145 | ```java 146 | public class LinkQueue { 147 | // 定义一个内部类Node,Node实例代表链队列的节点。 148 | private class Node { 149 | private T data;// 保存节点的数据 150 | private Node next;// 指向下个节点的引用 151 | 152 | // 初始化全部属性的构造器 153 | public Node(T data, Node next) { 154 | this.data = data; 155 | this.next = next; 156 | } 157 | } 158 | 159 | private Node front;// 保存该链队列的头节点 160 | private Node rear;// 保存该链队列的尾节点 161 | 162 | public LinkQueue() { 163 | // 空链队列,front和rear都是null 164 | front = null; 165 | rear = null; 166 | } 167 | 168 | public LinkQueue(T element) { 169 | front = new Node(element, null); 170 | // 只有一个节点,front、rear都指向该节点 171 | rear = front; 172 | } 173 | 174 | /** 175 | * 入队 176 | * 177 | * @param element 178 | */ 179 | public void offer(T element) { 180 | Node newNode = new Node(element, null);// 创建新节点 181 | // 如果该链队列还是空链队列 182 | if (front == null) { 183 | front = newNode; 184 | rear = front; // 只有一个节点,front、rear都指向该节点 185 | } else { 186 | rear.next = newNode;// 让尾节点的next指向新增的节点 187 | rear = newNode;// 以新节点作为新的尾节点 188 | } 189 | } 190 | 191 | /** 192 | * 出队 193 | * @return 194 | */ 195 | public T poll() { 196 | if (front == null ) { 197 | return null; 198 | } 199 | Node oldFront = front; 200 | front = front.next; // 将队头指针更改为指向 下一个节点 201 | oldFront.next = null; 202 | return oldFront.data; 203 | } 204 | 205 | public static void main(String[] args) { 206 | LinkQueue q = new LinkQueue<>(); 207 | q.offer("张三"); 208 | q.offer("李斯"); 209 | q.offer("赵五"); 210 | q.offer("神兽"); 211 | for (int i = 0; i < 5; i++) { 212 | System.out.println(q.poll()); 213 | } 214 | } 215 | } 216 | 217 | // 输出: 218 | 张三 219 | 李斯 220 | 赵五 221 | 神兽 222 | null 223 | ``` 224 | 225 | -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/206967579.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/206967579.jpg -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/345348487878.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/345348487878.jpg -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/34fasafdfsadjukjhfeqvyuERTSG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/34fasafdfsadjukjhfeqvyuERTSG.png -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/5f26921094ec.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/5f26921094ec.jpg -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/uydorpvmgasnht.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/uydorpvmgasnht.png -------------------------------------------------------------------------------- /Algo/数据结构(4)队列/wfgg31q.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(4)队列/wfgg31q.png -------------------------------------------------------------------------------- /Algo/数据结构(5)链表/1120165-20171207161602113-1451349858.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(5)链表/1120165-20171207161602113-1451349858.png -------------------------------------------------------------------------------- /Algo/数据结构(5)链表/20160420134000174.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(5)链表/20160420134000174.png -------------------------------------------------------------------------------- /Algo/数据结构(5)链表/2019-06-02_183101.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(5)链表/2019-06-02_183101.png -------------------------------------------------------------------------------- /Algo/数据结构(5)链表/20190603-2548.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(5)链表/20190603-2548.png -------------------------------------------------------------------------------- /Algo/数据结构(5)链表/20190603-4125512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(5)链表/20190603-4125512.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 树:由根结点和若干子结点构成的结合体 4 | 5 | ![](./数据结构(6)树/2019-06-05_205958.png) 6 | 7 | ## 基础术语 8 | 9 | * **节点的度**:指一个结点的子树个数, 10 | * **树的度**:一棵树中,最大的节点的度称为树的度; 11 | 12 | * **叶结点或终端节点**:指度为零的结点,即没有子树的结点 13 | * **非终端节点或分支节点**:度不为0的节点; 14 | * **双亲节点或父节点**:若一个节点含有子节点,则这个节点称为其子节点的父节点; 15 | * **孩子节点或子节点**:一个节点含有的子树的根节点称为该节点的子节点; 16 | * **兄弟节点**:具有相同父节点的节点互称为兄弟节点; 17 | * **节点的层次**:从根开始定义起,根为第1层,根的子节点为第2层,以此类推; 18 | * **树的高度或`深度`**:树中节点的最大层次; 19 | * **堂兄弟节点**:双亲在同一层的节点互为堂兄弟; 20 | * **节点的祖先**:从根到该节点所经分支上的所有节点; 21 | * **子孙**:以某节点为根的子树中任一节点都称为该节点的子孙。 22 | * **森林**:由m(m>=0)棵互不相交的树的集合称为森林; 23 | 24 | ![](./数据结构(6)树/2019-06-24_212644.png) 25 | 26 | ## 树分类 27 | 28 | 二叉树:有n(n>=0) 结点组成的有限集合。此集合或为空、或由一个跟结点加上两个分别称为左右子树的,互不相交的二叉树组成。 29 | 30 | * 二叉树第 i 层上的结点数最多为 2 ^i-1^ 31 | * 高度为 k 的二叉树最多有2^k^-1 个几点 32 | 33 | ![](./数据结构(6)树/2019-06-05_211519.png) 34 | 35 | 分类 36 | 37 | * 无序树:树中任意节点的子结点之间没有顺序关系,这种树称为无序树,也称为自由树; 38 | 39 | * 有序树:树中任意节点的子结点之间有顺序关系,这种树称为有序树; 40 | 41 | * 二叉树:每个节点最多含有两个子树的树称为二叉树; 42 | 43 | * 完全二叉树:指一棵二叉树最下面的两层结点的度数可以小于 2 ,并且最下一层上的结点数都集中在该层最左边的若干位置上。 44 | 45 | * 满二叉树:每层的结点数都达到最大值即 深度为 k 且有 2^k^-1 个结点 46 | 47 | * 霍夫曼树:带权路径最短的二叉树称为哈夫曼树或最优二叉树; 48 | * 平衡二叉树:又称AVL树; 49 | * 左子树和右子树都是平衡二叉树 50 | * 左子树和右子树的深度(高度)之差的绝对值不超过1。 51 | * 常用实现方法有 **红黑树**、AVL、替罪羊树、Treap、伸展树 52 | 53 | ![](./数据结构(6)树/2019-06-05_213234.png) 54 | 55 | ![](./数据结构(6)树/2019-06-05_213224.png) 56 | 57 | 58 | 59 | 60 | 61 | ## 二叉树存储结构 62 | 63 | ### 顺序存储 64 | 65 | * 顺序存储指:不管给定的二叉树是不是完全二叉树,都看作完全二叉树,即按完全二叉树的层次次序(从上到下,从左到右)把各个结点依次存入数组中 66 | 67 | ![](./数据结构(6)树/2019-06-05_213755.png) 68 | 69 | ![](./数据结构(6)树/2019-06-05_214742.png) 70 | 71 | ### 链式存储 72 | 73 | 链式存储中,每个节点由数据员和三个指针组成,即链表结构 在加一个 尾指针 74 | 75 | ![](./数据结构(6)树/2019-06-05_215227.png) 76 | 77 | 78 | 79 | ## 遍历树 80 | 81 | 遍历树四种基本的遍历思想为: 82 | 83 | 前序遍历:根结点 ---> 左子树 ---> 右子树 84 | 85 | 中序遍历:左子树---> 根结点 ---> 右子树 86 | 87 | 后序遍历:左子树 ---> 右子树 ---> 根结点 88 | 89 | 层次遍历:仅仅需按层次遍历就可以 90 | 91 | ![](./数据结构(6)树/20150204101904649.jpg) 92 | 93 | 前序遍历:1 2 4 5 7 8 3 6 94 | 95 | 中序遍历:4 2 7 5 8 1 3 6 96 | 97 | 后序遍历:4 7 8 5 2 6 3 1 98 | 99 | 层次遍历:1 2 3 4 5 6 7 8 100 | 101 | 102 | 103 | **代码实现** 104 | 105 | ```java 106 | //采用递归方式:---->>>>>>>>>>>>> 107 | //前序遍历 108 | public void preOrderTraverse1(TreeNode root) { 109 | if (root != null) { 110 | System.out.print(root.val+" "); 111 | preOrderTraverse1(root.left); 112 | preOrderTraverse1(root.right); 113 | } 114 | } 115 | 116 | //中序遍历 117 | public void inOrderTraverse1(TreeNode root) { 118 | if (root != null) { 119 | inOrderTraverse1(root.left); 120 | System.out.print(root.val+" "); 121 | inOrderTraverse1(root.right); 122 | } 123 | } 124 | //后续遍历 125 | public void postOrderTraverse1(TreeNode root) { 126 | if (root != null) { 127 | postOrderTraverse1(root.left); 128 | postOrderTraverse1(root.right); 129 | System.out.print(root.val+" "); 130 | } 131 | } 132 | 133 | 134 | //层次遍历 135 | public void levelTraverse(TreeNode root) { 136 | if (root == null) { 137 | return; 138 | } 139 | LinkedList queue = new LinkedList<>(); 140 | queue.offer(root); 141 | while (!queue.isEmpty()) { 142 | TreeNode node = queue.poll(); 143 | System.out.print(node.val+" "); 144 | if (node.left != null) { 145 | queue.offer(node.left); 146 | } 147 | if (node.right != null) { 148 | queue.offer(node.right); 149 | } 150 | } 151 | } 152 | ``` 153 | 154 | ## 平衡二叉树 155 | 156 | ![](./数据结构(6)树/2019-06-05_222540.png) 157 | 158 | 平衡二叉树:又称AVL树; 159 | 160 | * 左子树和右子树都是平衡二叉树 161 | * 左子树和右子树的深度(高度)之差的绝对值不超过1。 162 | * 常用实现方法有 **红黑树**、AVL、替罪羊树、Treap、伸展树 163 | 164 | AVL树同二叉排序树一样,有遍历(先序、中序、后序),最大值与最小值,插入和删除,销毁二叉树等操作,除插入和删除与二叉排序树操作不同之外,其余均与二叉排序树相同 165 | 166 | 167 | 168 | ## 红黑树 169 | 170 | 红黑树(Red Black Tree) 是一种自平衡二叉查找树 171 | 172 | 红黑树和AVL树类似,都是在进行插入和删除操作时通过特定操作保持二叉查找树的平衡,从而获得较高的查找性能。 173 | 174 | 它可以在O(log n)时间内做查找,插入和删除,这里的n 是树中元素的数目。 175 | 176 | **特性:** 177 | 178 | * 红黑树是每个节点都带有颜色属性的二叉查找树,颜色或红色或黑色。 179 | 180 | * 性质1. 节点是红色或黑色。 181 | 182 | * 性质2. 根节点是黑色。 183 | 184 | * 性质3 每个红色节点的两个子节点都是黑色。(**从每个叶子到根的所有路径上不能有两个连续的红色节点**) 185 | 186 | * 性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。 187 | 188 | ![](./数据结构(6)树/9358d109b3de9c828cdb8e7c6481800a18d84382.jpg) 189 | 190 | 191 | 192 | 193 | 194 | ## B-tree 195 | 196 | 多路查找树 ( muitl-way search tree) ,其每一个结点的孩子数可以多于两个 , 且每一个结点处可以存储多个元素。 197 | 198 | 它的 4 种特殊形式 : 2-3 树、 2-3-4 树、 B 树和 B+树。 199 | 200 | B 树 (B-Tree ) 是一种平衡的多路查找树 , 2 -3 树和 2-3-4 树都是 B 树的特例。结点最大的孩子数目称为 B 树的阶 (order) ,因此, 2-3 树是 3 阶 B 树, 2-3-4 树是 4阶B树。 201 | 202 | 203 | 204 | **m阶B-Tree满足以下条件:** 205 | 206 | 1、每个节点最多拥有m个子树 207 | 208 | 2、根节点至少有2个子树 209 | 210 | 3、分支节点至少拥有m/2颗子树(除根节点和叶子节点外都是分支节点) 211 | 212 | 4、所有叶子节点都在同一层、每个节点最多可以有m-1个key,并且以升序排列 213 | 214 | -------------------------------------------------------------------------------- /Algo/数据结构(6)树/20150204101904649.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/20150204101904649.jpg -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_205958.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_205958.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_211519.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_211519.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_213224.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_213224.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_213234.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_213234.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_213755.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_213755.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_214742.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_214742.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_215227.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_215227.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-05_222540.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-05_222540.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/2019-06-24_212644.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/2019-06-24_212644.png -------------------------------------------------------------------------------- /Algo/数据结构(6)树/9358d109b3de9c828cdb8e7c6481800a18d84382.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/数据结构(6)树/9358d109b3de9c828cdb8e7c6481800a18d84382.jpg -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/1094457-20170225183236538-961758163.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/1094457-20170225183236538-961758163.png -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/140151tbt1kcsjbds6bsbd.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/140151tbt1kcsjbds6bsbd.jpg -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/140152c1b40emo0c54joff.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/140152c1b40emo0c54joff.jpg -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/1940317-ad940e1d1a16fc39.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/1940317-ad940e1d1a16fc39.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/32qE3uY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/32qE3uY.png -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/55505.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/55505.jpg -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015223238449-2146169197.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015223238449-2146169197.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015224719590-1433219824.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015224719590-1433219824.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015225645277-1151100000.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015225645277-1151100000.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015230557043-37375010.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015230557043-37375010.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015230936371-1413523412.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015230936371-1413523412.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015231308699-356134237.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015231308699-356134237.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015231740840-6968181.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015231740840-6968181.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20171015232453668-1397662527.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20171015232453668-1397662527.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/849589-20180331170017421-364506073.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/849589-20180331170017421-364506073.gif -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/eaENbmi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/eaENbmi.png -------------------------------------------------------------------------------- /Algo/算法-基础篇(1)十大排序/m6RriyQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Algo/算法-基础篇(1)十大排序/m6RriyQ.png -------------------------------------------------------------------------------- /Algo/算法-基础篇(2)七大查询.md: -------------------------------------------------------------------------------- 1 | 查询算法中,最常见的有 7 种,分别是:顺序查询、二分查询、插值查询、斐波那契查询、树表查询、分库查询、哈希查询 2 | 3 | 4 | 5 | # 顺序查找 6 | 7 | ## 算法简介 8 | 9 | ​ 顺序查找又称为线性查找,是一种最简单的查找方法。适用于线性表的顺序存储结构和链式存储结构。该算法的时间复杂度为O(n)。 10 | 11 | ## 基本思路 12 | 13 | ​ 从第一个元素m开始逐个与需要查找的元素x进行比较,当比较到元素值相同(即m=x)时返回元素m的下标,如果比较到最后都没有找到,则返回-1。 14 | 15 | ## 优缺点 16 | 17 | ​ 缺点:是当n 很大时,平均查找长度较大,效率低; 优点:是对表中数据元素的存储没有要求。另外,对于线性链表,只能进行顺序查找。 18 | 19 | 20 | 21 | 22 | 23 | # 二分查找 24 | 25 | ## 算法简介 26 | 27 | ​ 二分查找(Binary Search),是一种在有序数组中查找某一特定元素的查找算法。查找过程从数组的中间元素开始,如果中间元素正好是要查找的元素,则查找过程结束;如果某一特定元素大于或者小于中间元素,则在数组大于或小于中间元素的那一半中查找,而且跟开始一样从中间元素开始比较。如果在某一步骤数组为空,则代表找不到。 这种查找算法每一次比较都使查找范围缩小一半。 28 | 29 | ## 算法描述 30 | 31 | 给予一个包含 n个带值元素的数组A 32 | 33 | * 1、 令 L为0 , R为 n-1 ; 34 | * 2、 如果L>R,则搜索以失败告终 ; 35 | * 3、 令 m (中间值元素)为 ⌊(L+R)/2⌋; 36 | * 4、 如果 AmT,令 R为 m - 1 并回到步骤二; 38 | 39 | ## 复杂度分析 40 | 41 | ​ 时间复杂度:折半搜索每次把搜索区域减少一半,时间复杂度为 O(logn) 空间复杂度:O(1) 42 | 43 | 44 | 45 | ## 代码实现 46 | 47 | ```java 48 | //二分查找,递归版本 49 | public class BinarySearch2{ 50 | //递归查找 51 | public static int binarysearch(int[] a,int value,int low,int high){ 52 | int mid = (low + high)/2; 53 | if(value == a[mid]){ 54 | return mid; 55 | }else if(value < a[mid]) 56 | return binarysearch(a,value,low,mid - 1); 57 | }else if(value > a[mid]) 58 | return binarysearch(a,value,mid + 1,high); 59 | } 60 | return -1; 61 | } 62 | //循环查找 63 | public static int binarysearch(int[] a,int value){ 64 | int left=0; 65 | int right=a.length-1; 66 | int middle=0; 67 | while(left<=right) { 68 | middle=(left+right)/2; 69 | if(value == a[middle]){ 70 | return middle; 71 | }else if(value < a[middle]) { 72 | left=middle - 1; 73 | }else if(value > a[middle]) { 74 | right=middle + 1; 75 | } 76 | } 77 | return middle; 78 | } 79 | public static void main(String[] args) { 80 | //int[] a = {1,4,2,9,8,6,7,0,3,5} 81 | int[] a = {0,1,2,3,4,5,6,7,8,9}; 82 | System.out.println(binarysearch(a,4,0,a.length-1)); 83 | } 84 | } 85 | 86 | ``` 87 | 88 | 89 | 90 | # 插值查找 91 | 92 | ## 算法简介 93 | 94 | 插值查找是根据要查找的关键字key与查找表中最大最小记录的关键字比较后的 查找方法, 95 | 96 | 时间复杂度o(logn),空间复杂度:O(1)。 97 | 98 | 插入查找:**选择下标 = left + (right - left) * (key - arr[left])/(arr[right] - arr[left])** 99 | 100 | (1)序列为**有序序列** 101 | 102 | (2)根据公式选取比较值,相等返回下标,不相等则根据公式继续查找,未找到返回-1 103 | 104 | ## 代码实现 105 | 106 | ```java 107 | public static int insertSearch(int[] array, int key) { 108 | return search(array, key, 0, array.length - 1); 109 | } 110 | private static int search(int[] array, int key, int left, int right) { 111 | while (left <= right) { 112 | if (array[left] == array[right]) { 113 | if (array[left] == key) 114 | return left; 115 | else return -1; 116 | } 117 | int middle = left + (right-left)*(key-array[left])/(array[right]-array[left]); 118 | if (array[middle] == key) { 119 | return middle; 120 | } 121 | if (key < array[middle]) { 122 | right = middle - 1; 123 | } else { 124 | left = middle + 1; 125 | } 126 | } 127 | return -1; 128 | } 129 | 130 | ``` 131 | 132 | 133 | 134 | 135 | 136 | # 斐波那契查找 137 | 138 | 斐波那契数列我们都知道{0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 },前后的比值会越来越接近0.618,也就是黄金分割点。 139 | 140 | **查找条件:** 141 | 142 | (1)数据必须采用顺序存储结构; 143 | 144 | (2)数据必须有序。 145 | 146 | ```java 147 | public static void main(String[] args) { 148 | int[] array = { 1, 5, 15, 22, 25, 31, 39, 42, 47, 49, 59, 68,88 }; 149 | System.out.println("result: " + fbSearch(array, 42)); 150 | } 151 | 152 | public static int fbSearch(int[] array, int value) { 153 | if (array == null || array.length == 0) { 154 | return -1; 155 | } else { 156 | int length = array.length; 157 | int[] fb = makeFbArray(20);// 制造一个长度为20的斐波数列 158 | int k = 0; 159 | while (length > fb[k] - 1) {// 找出数组的长度在斐波数列(减1)中的位置,将决定如何拆分 160 | k++; 161 | } 162 | 163 | int[] temp = Arrays.copyOf(array, fb[k] - 1);// 构造一个长度为fb[k] - 1的新数列 164 | //对新构造的数组进行 元素补充 165 | for (int i = length; i < temp.length; i++) { 166 | if (i >= length) { 167 | temp[i] = array[length - 1]; 168 | } 169 | } 170 | int low = 0; 171 | int hight = array.length - 1; 172 | while (low <= hight) { 173 | int middle = low + fb[k - 1] - 1; 174 | if (temp[middle] > value) { 175 | hight = middle - 1; 176 | k = k - 1; 177 | } else if (temp[middle] < value) { 178 | low = middle + 1; 179 | k = k - 2; 180 | } else { 181 | if (middle <= hight) { 182 | return middle;// 若相等则说明mid即为查找到的位置 183 | } else { 184 | return hight;// middle的值已经大于hight,进入扩展数组的填充部分,即最后一个数就是要查找的数。 185 | } 186 | } 187 | } 188 | return -1; 189 | } 190 | } 191 | 192 | 193 | private static int[] makeFbArray(int length) { 194 | int[] array = null; 195 | if (length > 2) { 196 | array = new int[length]; 197 | array[0] = 1; 198 | array[1] = 1; 199 | for (int i = 2; i < length; i++) { 200 | array[i] = array[i - 1] + array[i - 2]; 201 | } 202 | } 203 | return array; 204 | } 205 | ``` 206 | 207 | 208 | 209 | # 树表查找 210 | 211 | (------------正在整理中------------) 212 | 213 | # 分块查找 214 | 215 | (------------正在整理中------------) 216 | 217 | # 哈希查找 218 | 219 | (------------正在整理中------------) -------------------------------------------------------------------------------- /Algo/算法-基础篇(3)加密算法.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 常见的加密算法可以分成三类,**对称加密算法,非对称加密算法和散列算法**。 4 | 5 | 对称加密就是加密用的密码和解密用的密码是一样的,非对称就是加密和解密用的密钥不一样 6 | 7 | # 对称加密算法 8 | 9 | * 指加密和解密使用相同密钥的加密算法。 10 | * 优点在于加解密的高速度和使用长密钥时的难破解性 11 | 12 | 常见的对称加密算法有:**DES、AES** 、**Base64**、3DES、DESX、Blowfish、IDEA、RC4、RC5、RC6 13 | 14 | ## DES加密算法 15 | 16 | * DES加密算法是一种分组密码,加密解密用同一算法 17 | 18 | ## AES加密算法 19 | 20 | * AES加密算法是密码学中的高级加密标准 21 | 22 | ## Base64加密算法 23 | 24 | Base64是网络上最常见的用于传输8Bit字节代码字节代码)的编码方式之一,Base64编码可用于在HTTP环境下传递较长的标识信息 25 | 26 | ```xml 27 | 28 | org.apache.commons 29 | commons-lang3 30 | 3.3.2 31 | 32 | ``` 33 | 34 | ```java 35 | //对给定的字符串进行base64解码操作 36 | public static String decodeData(String inputData) { 37 | try { 38 | if (null == inputData) { 39 | return null; 40 | } 41 | return new String(Base64.decodeBase64(inputData.getBytes("utf-8")), "utf-8"); 42 | } catch (UnsupportedEncodingException e) { 43 | logger.error(inputData, e); 44 | } 45 | 46 | return null; 47 | } 48 | 49 | //对给定的字符串进行base64加密操作 50 | public static String encodeData(String inputData) { 51 | try { 52 | if (null == inputData) { 53 | return null; 54 | } 55 | return new String(Base64.encodeBase64(inputData.getBytes("utf-8")), "utf-8"); 56 | } catch (UnsupportedEncodingException e) { 57 | logger.error(inputData, e); 58 | } 59 | 60 | return null; 61 | } 62 | 63 | public static void main(String args[]){ 64 | String encodeStr=Base64Util.encodeData("龙不吟,虎不啸"); 65 | System.out.println("encodeStr="+encodeStr); 66 | String decodeStr=Base64Util.decodeData(encodeStr); 67 | System.out.println("decodeStr="+decodeStr); 68 | } 69 | ``` 70 | 71 | 72 | 73 | # 非对称加密算法 74 | 75 | * 指加密和解密使用不同密钥的加密算法,也称为公私钥加密 76 | * 缺点是加解密速度要远远慢于对称加密,在某些极端情况下,甚至能比非对称加密慢上1000倍。 77 | 78 | 常见的非对称加密算法有:**RSA** 、**DSA** (数字签名用)、ECC(移动设备用)、Diffie-Hellman、El Gamal 79 | 80 | 81 | 82 | **RSA** :非对称加密算法需要两个密钥:公开密钥(publickey)和私有密钥(privatekey) 83 | 84 | * RSA加密算法是目前最有影响力的公钥加密算 法,并且被普遍认为是**目前最优秀的公钥方案之一**。 85 | * RSA是第一个能同时用于加密和数宇签名的算法,它能够抵抗到目前为止已知的所有密码攻击,已被ISO推 荐为公钥数据加密标准。 86 | 87 | **RSA2** :用于对接支付宝时使用 88 | 89 | 90 | 91 | 92 | 93 | # 散列算法 94 | 95 | * 加密性强的散列一定是不可逆的 96 | * 单向散列函数一般用于产生消息摘要,密钥加密等 97 | 98 | 常见散列加密算法有:**MD5 、SHA-1** 99 | 100 | MD5 :是RSA数据安全公司开发的一种单向散列算法,非可逆,相同的明文产生相同的密文。 101 | 102 | **SHA** : 103 | 104 | * SHA1是和MD5一样流行的消息摘要算法。 105 | * 可以对任意长度的数据运算生成一个160位的数值; -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(1)Explain分析.md: -------------------------------------------------------------------------------- 1 | 在 MySQL 性能优化中,慢查询优化是我们经常需要解决的问题。通常我们可以使用 Explain 命令来了解 SQL 语句的执行计划,仅对select语句有效 2 | 3 | 4 | 5 | # **Explain** 6 | 7 | 代码演示如下 8 | 9 | ![](./MySQL-进阶之Explain详解/clipboard.png) 10 | 11 | 12 | 13 | explain 查询会输出 12 列,如:id、select_type、table、partitions、type、possible_keys、key、key_len、ref、rows、filtered、extra 14 | 15 | 以下分别介绍一下,其中type 和 key 是我们看一个SQL 性能好坏的重点。 16 | 17 | 18 | 19 | ## select_type 20 | 21 | 表示查询类型,主要用于区别普通查询,联合查询,子查询等的复杂查询 22 | 23 | > **SIMPLE**:简单SELECT(不使用UNION或子查询) 24 | > 25 | > **PRIMARY**:最外面的SELECT 26 | > 27 | > **UNION**:UNION中的第二个或后面的SELECT语句 28 | > 29 | > **DEPENDENT UNION**:UNION中的第二个或后面的SELECT语句,取决于外面的查询 30 | > 31 | > **UNION RESULT**:UNION 的结果 32 | > 33 | > **SUBQUERY**:子查询中的第一个SELECT 34 | > 35 | > **DEPENDENT SUBQUERY**:子查询中的第一个SELECT,取决于外面的查询 36 | > 37 | > **DERIVED**:导出表的SELECT(FROM子句的子查询) 38 | 39 | 40 | 41 | **table**数据库中表名称或别名 42 | 43 | 44 | 45 | ## type 46 | 47 | 表示对表访问方式;常用的类型有: **ALL、index、range、 ref、eq_ref、const、system、NULL(从左到右,性能从差到好)** 48 | 49 | **注意:一般保证查询至少达到range级别,最好能达到ref** 50 | 51 | > **ALL**:Full Table Scan, MySQL将遍历全表以找到匹配的行 52 | > 53 | > **index**:Full Index Scan,index与ALL区别为index类型只遍历索引树 54 | > 55 | > **range**:只检索给定范围的行,如: between/in、> 、< 、in 等方式 56 | > 57 | > **ref**:表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值 58 | > 59 | > **eq_ref**: 类似ref,区别就在使用的索引是唯一索引,对于每个索引键值,表中只有一条记录匹配,简单来说,就是多表连接中使用primary key或者 unique key作为关联条件 60 | > 61 | > **const/system**: 当MySQL对查询最多有一个匹配行,在这行的列值可被优化器剩余部分认为是常数。如将主键置于where列表中,MySQL就能将该查询转换为一个常量,system是const类型的特例,当查询的表只有一行的情况下,使用system 62 | > 63 | > **NULL**:MySQL在优化过程中分解语句,执行时甚至不用访问表或索引,例如从一个索引列里选取最小值可以通过单独索引查找完成。 64 | 65 | 66 | 67 | ## possible_keys 68 | 69 | 指出MySQL能使用哪个索引在表中找到记录,查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询使用(该查询可以利用的索引,如果没有任何索引显示 null) 70 | 71 | 72 | 73 | ## key 74 | 75 | **显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。** 76 | 77 | 78 | 79 | **key_len**:表示索引中使用的字节数 80 | 81 | **ref**:列与索引的比较,表示上述表的连接匹配条件,即哪些列或常量被用于查找索引列上的值 82 | 83 | **rows**:估算出结果集行数,表示MySQL根据表统计信息及索引选用情况,估算的找到所需的记录所需要读取的行数 84 | 85 | 86 | 87 | ## Extra 88 | 89 | > Using index:表示相应的select操作用使用覆盖索引,避免访问了表的数据行。如果同时出现using where,表名索引被用来执行索引键值的查找;如果没有同时出现using where,表名索引用来读取数据而非执行查询动作。 90 | > 91 | > Using where:表明使用where过滤,当有where子句时,extra都会有说明。 92 | > 93 | > Using temporary:表示需要使用临时表来存储结果集,常见于排序和分组查询,常见 group by ; order by 94 | > 95 | > Using filesort:当Query中包含 order by 操作,而且无法利用索引完成的排序操作称为“文件排序” 96 | > 97 | > Distinct:发现第1个匹配行后,停止为当前的行组合搜索更多的行 98 | > 99 | > Not exists:表示MySQL能够对查询进行LEFT JOIN优化,发现1个匹配LEFT JOIN标准的行后,不再为前面的的行组合在该表内检查更多的行。 100 | > 101 | > Range checked for each record:mysql没有发现好的索引可用,速度比没有索引要快得多。 102 | > 103 | > Using sort_union(...)/Using union(...)/Using intersect(...):表明 index_merge 联接类型合并索引扫描。 104 | > 105 | > Using index for group-by:表明可以在索引中找到GROUP BY或DISTINCT所需的所有数据,不需要查询实际的表。 106 | 107 | 108 | 109 | **资料参考** 110 | 111 | * 高性能MySQL(第3版).pdf -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(1)Explain分析/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(1)Explain分析/clipboard.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471069260.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471069260.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471075930.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471075930.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471080641.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471080641.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471104139.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471104139.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471160438.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471160438.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471163906.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471163906.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471203419.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471203419.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471209120.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471209120.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471258868.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471258868.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471265870.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471265870.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471272332.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471272332.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471286651.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471286651.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471336181.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471336181.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471349135.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471349135.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471351583.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471351583.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471370829.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471370829.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471414535.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471414535.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471420298.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471420298.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471429052.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471429052.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471433168.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471433168.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471442067.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471442067.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471446600.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471446600.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471483435.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471483435.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471487375.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471487375.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471491098.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471491098.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471502361.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471502361.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471505672.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard-1585471505672.png -------------------------------------------------------------------------------- /DB/MySQL数据库-优化篇(2)SQL优化/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-优化篇(2)SQL优化/clipboard.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(1)存储引擎/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(1)存储引擎/clipboard.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(2)事务与锁.md: -------------------------------------------------------------------------------- 1 | # 事务 2 | 3 | ## ACID特性 4 | 5 | 总得来说,事务是为了保证数据的安全性,一致性,正确性。必须满足所谓的**ACID**(原子性、一致性、隔离性和持久性)属性 6 | 7 | * **原子性(Atomic)**,事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行 8 | * **一致性(Consistent)**,事务的执行结果,必须是从一个一致状态,变成另一个新的一致状态。事务的原子性保证其一致性 9 | * **隔离性(Isolation)**,主要在并发时,各个事务之间互不影响。并发事务所作的修改必须与任何其它并发事务所作的修改隔离。 10 | * **持久性(Duration)**,事务一旦提交,数据就永久的保存在数据库,它对于系统的影响是永久性的。 11 | 12 | ## 事务问题 13 | 14 | 并发操作通常会带来一些事务问题,如下 15 | 16 | * 更新丢失:两个不同的事务(或者Java程序线程)在某一时刻对同一数据进行读取后,先后进行修改。导致第一次操作数据丢失。 17 | * 脏读:指一个事务读取了另外一个事务未提交的数据。 18 | * 不可重复读:指在一个事务内读取表中的某一行数据,多次读取结果不同。该问题重点是修改,同样的条件,你读取过的数据,再次读取出来发现值不一样了 19 | * 幻读:一个事务的两次不同时间的相同查询返回了不同的的结果集。该问题重点在于新增或者删除,同样的条件,第 1 次和第 2 次读出来的记录数不一样 20 | 21 | **SQL中对数据的修改分为更新、插入和删除,分别对应三种不可重复读的问题,后两种问题也被称为“幻读”。** 22 | 23 | 24 | 25 | ## 事务隔离级别 26 | 27 | | 事务隔离级别 | 脏读 | 不可重复读 | 幻读 | 28 | | ---------------------------- | ---- | ---------- | ---- | 29 | | 读未提交(read-uncommitted) | 是 | 是 | 是 | 30 | | 不可重复读(read-committed) | 否 | 是 | 是 | 31 | | 可重复读(repeatable-read) | 否 | 否 | 是 | 32 | | 串行化(serializable) | 否 | 否 | 否 | 33 | 34 | ## 事务控制语句 35 | 36 | * BEGIN 或 START TRANSACTION 显式地开启一个事务; 37 | * COMMIT 也可以使用 COMMIT WORK,不过二者是等价的。COMMIT 会提交事务,并使已对数据库进行的所有修改成为永久性的; 38 | * ROLLBACK 也可以使用 ROLLBACK WORK,不过二者是等价的。回滚会结束用户的事务,并撤销正在进行的所有未提交的修改; 39 | * SAVEPOINT identifier,SAVEPOINT 允许在事务中创建一个保存点,一个事务中可以有多个 SAVEPOINT; 40 | * RELEASE SAVEPOINT identifier 删除一个事务的保存点,当没有指定的保存点时,执行该语句会抛出一个异常; 41 | * ROLLBACK TO identifier 把事务回滚到标记点; 42 | * SET TRANSACTION 用来设置事务的隔离级别。InnoDB 存储引擎提供事务的隔离级别有READ UNCOMMITTED、READ COMMITTED、REPEATABLE READ 和 SERIALIZABLE。 43 | 44 | 45 | 46 | **MYSQL 事务处理主要有两种方法:** 47 | 48 | 1、用 BEGIN, ROLLBACK, COMMIT来实现 49 | 50 | * **BEGIN** 开始一个事务 51 | * **ROLLBACK** 事务回滚 52 | * **COMMIT** 事务确认 53 | 54 | 2、直接用 SET 来改变 MySQL 的自动提交模式: 55 | 56 | * **SET AUTOCOMMIT=0** 禁止自动提交 57 | * **SET AUTOCOMMIT=1** 开启自动提交 58 | 59 | 60 | 61 | 62 | 63 | # 锁 64 | 65 | 在《深入浅出MySQL++数据库开发、优化与管理维护+第2版+唐汉明》14中注明 66 | 67 | > MySQL 支持对MyISAM 和 MEMORY 存储引擎的表进行表级锁定,对BDB存储引擎的表进行页级锁定,对InnoDB存储引擎进行行级锁定。默认情况下,表锁和行锁都是自动获得的, 不需要额外的命令,但是在有点情况下,用户需要明确地进行锁表或进行事务的控制,以变确保整个事务的完整性,这样就需要使用事务控制和锁定语句来完成 68 | 69 | 在MySQL 中有存在 3 种锁:行级锁、表级锁和页级锁;MyISAM 和 MEMORY 存储引擎 采用表级锁; BDB 采用页面锁,也支持表级锁;InnoDB 默认支持行级锁,也支持表级锁 70 | 71 | MySQL的 3 种锁特性如下: 72 | 73 | * 表级锁:开销小,加锁快,不会出现死锁,颗粒度大,发生锁冲突概率高,并发度最低 74 | * 行级锁:开销大,加锁慢,会出现死锁,颗粒度最小,发生锁冲突概率最低,并发度最高 75 | * 页级锁,开销、加锁时间、颗粒度介于表锁和行锁之间 ,会出现死锁,并发一般 76 | 77 | 78 | 79 | ## 表锁 80 | 81 | MySQL 表锁有两种模式,共享读锁和独占写锁 82 | 83 | 对MyISAM来说,读锁,不会阻塞其他用户对同一表的读请求;写锁,会阻塞其他用户对同一表的读和写操作。 84 | 85 | 加锁方式如下: 86 | 87 | ```sql 88 | -- 加锁: 89 | lock tables table_name { read | write } [local] 90 | -- 解锁: 91 | unlock tables 92 | ``` 93 | 94 | 加锁时可以在 LOCK TABLES 时加了“local”选项,作用是在满足MyISAM 表并发插入条件的情况下,允许其他用户在表尾并发插入记录; 95 | 96 | **注意:**在用lock tables 加锁时,必须先获取得所涉及表的锁,且加锁后,只能访问这些表,不能访问未加锁的表。如果加的读锁,那么只能支持查询操作,不能更新 97 | 98 | 99 | 100 | ## 行锁 101 | 102 | **行级锁是一种排他锁,防止其他事务修改此行**,在使用以下语句时,Oracle 会自动应用行级锁。 103 | 104 | InnoDB行锁是通过给索引上的索引项加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则,InnoDB将使用表锁;如如果没有索引。InnoDB将通过隐藏的聚簇索引来对记录加锁,且**在没有索引的情况下,InnoDB会对所有的记录都加锁;**由于MySQL的行锁是针对索引加的锁,而不是记录,所以**当访问不同记录时,使用相同的索引键,是会出现锁冲突的**。换句话说,只要不是使用相同的索引键,是不会导致锁冲突的。 105 | 106 | ```sql 107 | 共享锁(S):SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE 108 | 排他锁(X):SELECT * FROM table_name WHERE ... FOR UPDATE 109 | 使用 COMMIT 或 ROLLBACK 语句释放锁。 110 | ``` 111 | 112 | 使用 LOCK IN SHARE MODE 获取共享锁很容易造成死锁问题。 -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(3)数据类型.md: -------------------------------------------------------------------------------- 1 | **数据类型** 2 | 3 | 在 MySQL中字段的数据类型有很多种,常见的可以分为几类,如:整型、浮点型、字符型、日期时间类型等。 4 | 5 | 6 | 7 | ## 整型 8 | 9 | 可以使用的整数类型有:TINYINT,SMALLINT,MEDIUMINT,INT,BIGINT。 10 | 11 | 分别使用 8、16、24、32、64位存储空间。存储范围从-2^(N-1)^ 到 2^(N-1)^ - 1,其中N是存储空间位数,一般情况下选择类型越小越好。 12 | 13 | | 整数类型 | 字节 | 最小值 | 最大值 | 14 | | --------- | ---- | --------------------------------- | --------------------------------------------------- | 15 | | TINYINT | 1 | 有符号-128无符号0 | 有符号127无符号255 | 16 | | SMALLINT | 2 | 有符号-32768无符号0 | 有符号32767无符号65535 | 17 | | MEDIUMINT | 3 | 有符号-8388608无符号0 | 有符号8388607无符号1677215 | 18 | | INT | 4 | 有符号-2147483648无符号0 | 有符号21474836487无符号 | 19 | | BIGINT | 8 | 有符号-9223372036854775808无符号0 | 有符号9223372036854775807无符号18446744073709551615 | 20 | 21 | 整数类型有可选的 unsigned 属性,表示不允许负值,可以使正数的上限提高一倍,例如:tinyint unsigned 范围是0~255,而tinyint 的存储范围是 128~127 22 | 23 | 整数类型可以指定宽度,如 int (n) :n 表示 zerofill 状态下,显示的最少字符长度,当字符长度不满足要求时,会用“0”自动填充。与存储空间大小无关(int 都在4个字节长度),看下图的 cid 字段就可知了, 24 | 25 | ![](MySQL数据库-基础篇(3)数据类型/1562926867684.png) 26 | 27 | ![](MySQL数据库-基础篇(3)数据类型/1562926888780.png) 28 | 29 | ## 浮点型和定点数 30 | 31 | FLOAT 和 DOUBLE 为浮点类型,DECIMAL 为高精度小数类型,常用于如,财务数据。 32 | 33 | FLOAT、DOUBLE 和 DECIMAL 都可以指定列宽,例如 DECIMAL(18, 9) 表示总共 18 位,取 9 位存储小数部分,剩下 9 位存储整数部分。 34 | 35 | 36 | 37 | ## 日期和时间型 38 | 39 | MySQL 提供了多种相似的日期时间类型,主要使用如下 40 | 41 | * 表示年月日:通常使用 DATE 42 | * 表示年月日时分秒:通常使用 DATETIME 和 TIMESTAMP 43 | * 表示时分秒:通常使用 TIME 44 | 45 | | 类型 | 字节 | 最小值 | 最大值 | 46 | | --------- | ---- | ------------------- | ------------------- | 47 | | YEAR | 1 | 1901 | 2155 | 48 | | TIME | 3 | -838:59:59 | 838:59:59 | 49 | | DATE | 4 | 1000-01-01 | 9999-12-31 | 50 | | TIMESTAMP | 4 | 1970-01-01 00:00:01 | 2038-01-19 03:14:07 | 51 | | DATETIME | 8 | 1000-01-01 00:00:00 | 9999-12-31 23:59:59 | 52 | 53 | 54 | 55 | **DATETIME 和 TIMESTAMP区别** 56 | 57 | **DATETIME:** 58 | 59 | 能够保存从 1001 年到 9999 年的日期和时间,精度为秒,使用 8 字节的存储空间。它与时区无关。 60 | 61 | 默认情况下,MySQL 以一种可排序的、无歧义的格式显示 DATETIME 值,例如“2008-01-16 22:37:08”,这是 ANSI 标准定义的日期和时间表示方法。 62 | 63 | **TIMESTAMP:** 64 | 65 | 和 UNIX 时间戳相同,保存从 1970 年 1 月 1 日午夜(格林威治时间)以来的秒数,使用 4 个字节,只能表示从 1970 年 到 2038 年。它和时区有关,也就是说一个时间戳在不同的时区所代表的具体时间是不同的。 66 | 67 | **最小值1970-01-01 00:00:01 通常和时区有关,一般需要加上8小时,如1970-01-01 08:00:01** 68 | 69 | MySQL 提供了 FROM_UNIXTIME() 函数把 UNIX 时间戳转换为日期,并提供了UNIX_TIMESTAMP() 函数把日期转换为 UNIX 时间戳。 70 | 71 | 默认情况下,如果插入时没有指定 TIMESTAMP 列的值,会将这个值设置为当前时间。应该尽量使用 TIMESTAMP,因为**它比 DATETIME 空间效率更高**。 72 | 73 | 74 | 75 | ## 字符型 76 | 77 | MySQL支持多种字符串类型,且每种类型还有很多变种。其中 varchar和char 为两种主要的类型 78 | 79 | * char(N):固定长度,当长度不够时自动填充至 n 个字符长度,最多255字符,占用N个字节。优点:不易产生空间碎片。 80 | * varchar(N):可变长度,比定长类型更省空间 ,需要1个或者2个字节表示长度(>=255时2个),最多65535字符,占用N+1个字节,优点:节省空间 81 | 82 | CHAR 存储时MySQL会删除所有的末尾空格,varchar 不会(4.1 之前会) 83 | 84 | ![](MySQL数据库-基础篇(3)数据类型/clipboard.png) 85 | 86 | 87 | 88 | ## 字符集 89 | 90 | 字符,我们主要关注一下支持中文的区别,在支持中文时,GBK每个汉字占2个字节,UTF-8则需要3个字节 91 | 92 | 93 | 94 | ## 资料参考 95 | 96 | * 深入浅出MySQL++数据库开发、优化与管理维护+第2版+唐汉明-6.pdf -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(3)数据类型/1562926867684.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(3)数据类型/1562926867684.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(3)数据类型/1562926888780.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(3)数据类型/1562926888780.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(3)数据类型/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(3)数据类型/clipboard.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数.md: -------------------------------------------------------------------------------- 1 | 本章内容请原谅我懒,直接抠图。 2 | 3 | ## 字符串函数 4 | 5 | 字符串函数通常是我们使用最普遍的,如下: 6 | 7 | ![](MySQL数据库-基础篇(4)常用函数/clipboard.png) 8 | 9 | ![](MySQL数据库-基础篇(4)常用函数/clipboard-1585469653610.png) 10 | 11 | ## 数值函数 12 | 13 | ![](MySQL数据库-基础篇(4)常用函数/clipboard-1585469711457.png) 14 | 15 | ## 日期和时间函数 16 | 17 | ![](MySQL数据库-基础篇(4)常用函数/clipboard-1585469721869.png) 18 | 19 | 20 | 21 | ```SQL 22 | -- 计算两个日期之间的时间间隔的方法 23 | select TimeStampDiff(DAY,'2019-01-01','2019-02-03') 24 | ``` 25 | 26 | 通常格式化时间表达式:**%Y-%m-%d %H:%i:%s** 27 | 28 | ![](MySQL数据库-基础篇(4)常用函数/clipboard-1585469752042.png) 29 | 30 | 31 | 32 | ## 资料参考 33 | 34 | * 深入浅出MySQL++数据库开发、优化与管理维护+第2版+唐汉明-6.pdf -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469653610.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469653610.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469711457.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469711457.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469721869.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469721869.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469752042.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(4)常用函数/clipboard-1585469752042.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(4)常用函数/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(4)常用函数/clipboard.png -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(5)索引.md: -------------------------------------------------------------------------------- 1 | MySQL 中索引时我们进行数据库优化时最常用,也是最有效的手段之一。这里主要讨论一下索引的分类、存储、使用方法 2 | 3 | # 索引的分类 4 | 5 | 在MySQL中通常有如下几类: 6 | 7 | 1. B-Tree:最常见的索引类型 8 | 2. HASH:只有Memory/Heap/NDB 支持 9 | 3. R-Tree(空间索引):是MyISAM的一个特殊索引类型,用于地理空间数据类型,使用较少 10 | 4. Full-text(全文索引):是MyISAM的一个特殊索引类型,用于全文索引,InnoDB从MySQL5.6版本开始支持 11 | 12 | 哈希索引 对于InnoDB来说,InnoDB在内部将哈希索引用于其自适应哈希索引功能,会根据表的使用情况自动为表生成哈希索引,因此不支持; 13 | 14 | 查看官方文档:https://dev.mysql.com/doc/refman/5.7/en/innodb-introduction.html ,我们可以找到 15 | 16 | ![](MySQL数据库-基础篇(5)索引/clipboard.png) 17 | 18 | 19 | 20 | **B-Tree 索引和 Hash 索引比较** 21 | 22 | 1. B树索引可以在使用表达式中使用的对列的比较 [=](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_equal), [>](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_greater-than), [>=](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_greater-than-or-equal), [<](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_less-than), [<=](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_less-than-or-equal),或[BETWEEN](https://dev.mysql.com/doc/refman/5.7/en/comparison-operators.html#operator_between),包括[LIKE](https://dev.mysql.com/doc/refman/5.7/en/string-comparison-functions.html#operator_like)是不以通配符开头的常量字符串,则索引也可以用于比较 23 | 2. 哈希索引仅用于使用=、<=> 运算符的相等比较 (但*非常*快),但不能用于范围查询 24 | 3. MySQL无法确定两个值之间大约有多少行(范围优化器使用它来决定使用哪个索引)。如果将MyISAM或 InnoDB表更改为哈希索引MEMORY表,这可能会影响某些查询。 25 | 4. 哈希索引仅整个键可用于搜索行。(对于B树索引,键的任何最左边的前缀都可用于查找行。) 26 | 27 | 28 | 29 | # 索引使用场景 30 | 31 | ## 索引典型场景 32 | 33 | 1. 全值匹配 34 | 2. 范围查询 35 | 3. 最左匹配原则 36 | 4. 覆盖索引 37 | 5. 前缀索引 38 | 6. 索引列使用is null 39 | 40 | 41 | 42 | ## 不能使用索引的场景 43 | 44 | 1. 以%开头的LIKE查询不能够利用 B-Tree 索引。可采用全文索引解决此问题 45 | 2. 隐式转换也不会使用索引,特别注意当列是字符串,那么常量值一定要用引号,否则无法使用该列上的索引 46 | 3. 复合索引的情况下,当不满足最左原则时也不会使用复合索引 47 | 4. 如果使用索引比全表更慢,也不会使用索引 48 | 5. 使用or时,如果前面的列有索引,后面的列没有,那么所涉及的索引都不会被用到 49 | 50 | 51 | 52 | # 查看索引使用情况 53 | 54 | **1、查询当前索引使用情况** 55 | 56 | SHOW STATUS LIKE 'Handler_read%'; 57 | 58 | * Handler_read_first:代表读取索引头的次数,如果这个值很高,说明全索引扫描很多。 59 | * Handler_read_key:代表一个索引被使用的次数,如果我们新增加一个索引,可以查看Handler_read_key是否有增加,如果有增加,说明sql用到索引。 60 | * Handler_read_next:代表读取索引的下列,一般发生range scan。 61 | * Handler_read_prev:代表读取索引的上列,一般发生在ORDER BY … DESC。 62 | * Handler_read_rnd:代表在固定位置读取行,如果这个值很高,说明对大量结果集进行了排序、进行了全表扫描、关联查询没有用到合适的KEY。 63 | * Handler_read_rnd_next:代表进行了很多表扫描,查询性能低下。 64 | 65 | **2、查看索引是否被使用到** 66 | 67 | ```sql 68 | SELECT object_type, object_schema, object_name, index_name, count_star, count_read, COUNT_FETCH FROM PERFORMANCE_SCHEMA.table_io_waits_summary_by_index_usage; 69 | ``` 70 | 71 | 如果read,fetch的次数都为0的话,就是没有被使用过的。 72 | 73 | **3、查看SQL用到了什么索引** 74 | 75 | 可以使用explain,从最好到最差依次是:system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > ALL -------------------------------------------------------------------------------- /DB/MySQL数据库-基础篇(5)索引/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/DB/MySQL数据库-基础篇(5)索引/clipboard.png -------------------------------------------------------------------------------- /Design/设计模式(1)工厂模式.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 工厂模式 4 | 5 | > 定义一个创建对象的接口,让其子类自己决定实例化哪一个工厂类,工厂模式使其创建过程延迟到子类进行 6 | 7 | **主要解决**:主要解决接口选择的问题。 8 | 9 | **优点**: 1、一个调用者想创建一个对象,只要知道其名称就可以了。 2、扩展性高,如果想增加一个产品,只要扩展一个工厂类就可以。 3、屏蔽产品的具体实现,调用者只关心产品的接口。 10 | 11 | **缺点**:每次增加一个产品时,都需要增加一个具体类和对象实现工厂,使得系统中类的个数成倍增加,在一定程度上增加了系统的复杂度,同时也增加了系统具体类的依赖。这并不是什么好事。 12 | 13 | **实现方式**:让工厂类根据名称创建对象,并返回该对象的抽象类 14 | 15 | 16 | 17 | # 实现 18 | 19 | 场景:大家可能不知道,本人是从一个大山深处的一户果农家走出的孩子,最近家那边修了马路,有不少批发商去采购水果,什么桃啊、李啊、橘啊、西瓜啊等各种水果。他们根本不关心你是怎么种出来的,只要知道这里能收到某种水果,能以低价收购就成。 20 | 21 | 所以这里以批发商收购水果进行模拟。 22 | 23 | ## 步骤1 24 | 25 | 我们想卖出自己的农产品,就得让人家知道你的价格,我们先创建一个水果的接口类 26 | 27 | Fruit.java 28 | 29 | ```java 30 | public interface Fruit { 31 | void price(); 32 | } 33 | ``` 34 | 35 | ## 步骤2 36 | 37 | 既然卖农产品,就得有产品是吧,所以这里创建接口的实现类,这里就演示 2 种水果桃子、橘子 38 | 39 | Peach.java 40 | 41 | ```java 42 | public class Peach implements Fruit { 43 | @Override 44 | public void price() { 45 | System.out.println("桃子11.9"); 46 | } 47 | } 48 | ``` 49 | 50 | Orange.java 51 | 52 | ```java 53 | public class Orange implements Fruit { 54 | @Override 55 | public void price() { 56 | System.out.println("橘子5.8"); 57 | } 58 | } 59 | ``` 60 | 61 | ## 步骤3 62 | 63 | 交易市场,怎么理解呢?批发商来收购水果,不可能自己一家家进行拜访吧,所以会有有个地方进行组织,就是交易市场的意思。批发商只要来到这个地方,报出你要进购的水果可以了,避免了自己一家家上门收购。 64 | 65 | FruitFactor.java 66 | 67 | ```java 68 | public class FruitFactory { 69 | /** 70 | * 通过名称获取水果对象 71 | * @param name 72 | * @return 73 | */ 74 | public Fruit buyFruit(FruitEnum name) { 75 | if (name == null) { 76 | return null; 77 | } 78 | if (FruitEnum.PEACH == name) { 79 | return new Peach(); 80 | } 81 | if (FruitEnum.ORANGE == name) { 82 | return new Orange(); 83 | } 84 | return null; 85 | } 86 | } 87 | ``` 88 | 89 | 这里增加了枚举类作为常量值 90 | 91 | 92 | 93 | ## 步骤4 94 | 95 | 通过交易市进购取水果,获取水果实现类的对象 96 | 97 | Main.java 98 | 99 | ```java 100 | public class Main { 101 | public static void main(String[] args) { 102 | FruitFactory factory = new FruitFactory(); 103 | 104 | // 获取桃子对象 105 | Fruit peach = factory.buyFruit(FruitEnum.PEACH); 106 | peach.price(); 107 | 108 | // 获取橘子对象 109 | Fruit orange = factory.buyFruit(FruitEnum.ORANGE); 110 | orange.price(); 111 | } 112 | } 113 | ``` 114 | 115 | 116 | 117 | [GitHub 源码](https://github.com/HusyCoding/java-design-pattern.git) 118 | 119 | -------------------------------------------------------------------------------- /Design/设计模式(2)抽象工厂模式.md: -------------------------------------------------------------------------------- 1 | # 抽象工厂模式 2 | 3 | > 提供一个创建一系列相关或相互依赖对象的接口,而无需指定它们具体的类 4 | 5 | **主要解决:**主要解决接口选择的问题。 6 | 7 | **优点:**当一个产品族中的多个对象被设计成一起工作时,它能保证客户端始终只使用同一个产品族中的对象。 8 | 9 | **缺点:**产品族扩展非常困难,要增加一个系列的某一产品,既要在抽象的 Creator 里加代码,又要在具体的里面加代码。 10 | 11 | **使用场景:** 1、QQ 换皮肤,一整套一起换。 2、生成不同操作系统的程序。 12 | 13 | **实现方式**:在工厂模式上,增加抽象工厂类,且让所有的工厂类继承该抽象工厂类,即并行运行两套工厂模式 14 | 15 | 16 | 17 | # 实现 18 | 19 | 场景:在工厂模式中,我们并没有明确买哪种产品,因此我们加入品牌进行模拟一下 20 | 21 | 1、先定义配件抽象类(这个类可以不用定义) 22 | 23 | ```java 24 | public abstract class Parts { 25 | String brand; 26 | String typeName; 27 | double price; 28 | 29 | public Parts(String typeName, double price,String brand) { 30 | this.typeName = typeName; 31 | this.price = price; 32 | this.brand = brand; 33 | } 34 | public void print() { 35 | System.out.println("配件类型/品牌/价格:" + typeName + "," + brand + "," + price); 36 | } 37 | } 38 | ``` 39 | 40 | 2、定义华为配件抽象类和其实现类 41 | 42 | ```java 43 | public abstract class HUAWEIParts extends Parts{ 44 | public HUAWEIParts(String typeName,double price) { 45 | super(typeName,price,"华为(HUAWEI)"); 46 | } 47 | } 48 | ``` 49 | 50 | ```java 51 | public class HUAWEIKeyboard extends HUAWEIParts { 52 | public HUAWEIKeyboard() { 53 | super("键盘", 30); 54 | } 55 | } 56 | ``` 57 | 58 | ```java 59 | public class HUAWEIMouse extends HUAWEIParts{ 60 | public HUAWEIMouse() { 61 | super("鼠标", 20); 62 | } 63 | } 64 | ``` 65 | 66 | 3、定义戴尔配件抽象类和其实现 67 | 68 | ```java 69 | public abstract class DELLParts extends Parts { 70 | public DELLParts(String typeName, double price) { 71 | super(typeName,price,"戴尔(DELL)"); 72 | } 73 | } 74 | ``` 75 | 76 | ```java 77 | public class DELLKeyboard extends DELLParts { 78 | public DELLKeyboard() { 79 | super("键盘", 35); 80 | } 81 | } 82 | ``` 83 | 84 | ```java 85 | public class DELLMouse extends DELLParts{ 86 | public DELLMouse() { 87 | super("鼠标", 25); 88 | } 89 | } 90 | ``` 91 | 92 | 4、创建电脑城抽象工厂和其专卖店的实现类(这里是关键,指明了多个工厂的共同父类) 93 | 94 | ```java 95 | public abstract class StoreFactory { 96 | public abstract Parts buy(PartsEnum type); 97 | } 98 | ``` 99 | 100 | ```java 101 | //华为商铺工厂类 102 | public class HUAWEIStoreFactory extends StoreFactory { 103 | //这个方法通常为静态方法,调用时不用实例化。这里就不写了 104 | @Override 105 | public Parts buy(PartsEnum type) { 106 | if (type == null) { 107 | return null; 108 | } 109 | if (PartsEnum.HUAWEI_MOUSE == type) { 110 | return new HUAWEIMouse(); 111 | }else if (PartsEnum.HUAWEI_KEYBOARD == type) { 112 | return new HUAWEIKeyboard(); 113 | } 114 | return null; 115 | } 116 | } 117 | ``` 118 | 119 | ```java 120 | //戴尔商铺工厂类 121 | public class DELLStoreFactory extends StoreFactory { 122 | //这个方法通常为静态方法,调用时不用实例化。这里就不写了 123 | @Override 124 | public Parts buy(PartsEnum type) { 125 | if (type == null) { 126 | return null; 127 | } 128 | if (PartsEnum.DELL_MOUSE == type) { 129 | return new DELLMouse(); 130 | }else if (PartsEnum.DELL_KEYBOARD == type) { 131 | return new DELLKeyboard(); 132 | } 133 | return null; 134 | } 135 | } 136 | ``` 137 | 138 | 测试类: 139 | 140 | ``` 141 | public static void main(String[] args) { 142 | //1、小明来到电脑城,先定义电脑城工厂类 143 | StoreFactory factory=null; 144 | 145 | //2、小明来到华为专卖店,实例化华为专卖店 146 | factory = new HUAWEIStoreFactory(); 147 | //3、向销售员说明需购买的产品--鼠标 148 | Parts parts = factory.buy(PartsEnum.HUAWEI_MOUSE); 149 | parts.print(); 150 | 151 | 152 | //4、小明来再到戴尔专卖店,实例化戴尔专卖店 153 | factory = new DELLStoreFactory(); 154 | //5、向销售员说明需购买的产品--键盘 155 | parts = factory.buy(PartsEnum.DELL_MOUSE); 156 | parts.print(); 157 | } 158 | ``` 159 | 160 | 执行输出以下结果: 161 | 162 | 配件类型/品牌/价格:鼠标,华为(HUAWEI),20.0 163 | 164 | 配件类型/品牌/价格:鼠标,戴尔(DELL),25.0 165 | 166 | 167 | 168 | # 资料参考 169 | 170 | * [设计模式 | 菜鸟教程](https://www.runoob.com/design-pattern/design-pattern-tutorial.html) 171 | 172 | * Head First设计模式 -------------------------------------------------------------------------------- /Design/设计模式(3)单例模式.md: -------------------------------------------------------------------------------- 1 | # 单例模式 2 | 3 | > 保证一个类仅有一个实例,并提供一个访问它的全局访问点。 4 | 5 | **主要解决**:一个全局使用的类频繁地创建与销毁。 6 | 7 | **优点**: 8 | 9 | * 在内存里只有一个实例,减少了内存的开销,尤其是频繁的创建和销毁实例(比如管理学院首页页面缓存)。 10 | * 避免对资源的多重占用(比如写文件操作)。 11 | 12 | **缺点:**没有接口,不能继承,与单一职责原则冲突,一个类应该只关心内部逻辑,而不关心外面怎么样来实例。 13 | 14 | **使用场景**: 15 | 16 | * 要求生产唯一序列号。 17 | * WEB 中的计数器,不用每次刷新都在数据库里加一次,用单例先缓存起来。 18 | * 创建的一个对象需要消耗的资源过多,比如 I/O 与数据库的连接等。 19 | 20 | **单例模式有以下特点**: 21 | 22 | * 单例类只能有一个实例。 23 | * 单例类必须自己创建自己的唯一实例。 24 | * 单例类必须给所有其他对象提供这一实例。 25 | 26 | **注意**:getInstance() 方法中需要使用同步锁 synchronized (Singleton.class) 防止多线程同时进入造成 instance 被多次实例化。 27 | 28 | 29 | 30 | **单例模式的几种实现方式** 31 | 32 | 单例模式实现有 5 种方式,如:懒汉式、饿汉式、双检锁/双重校验锁、登记式/静态内部类、枚举式 33 | 34 | **经验之谈:**一般情况下,不建议使用懒汉方式,建议使用饿汉方式。只有在要明确实现 lazy loading 效果时,才会使用登记方式。如果涉及到反序列化创建对象时,可以尝试使用第 6 种枚举方式。如果有其他特殊的需求,可以考虑使用第 4 种双检锁方式。 35 | 36 | 37 | 38 | **需要思考的问题** 39 | 40 | * 为什么说饿汉式单例天生就是线程安全的? 41 | * 传统的懒汉式单例为什么是非线程安全的? 42 | * 怎么修改传统的懒汉式单例,使其线程变得安全? 43 | * 线程安全的单例的实现还有哪些,怎么实现? 44 | 45 | 46 | 47 | **立即加载和延迟加载** 48 | 49 | * 立即加载 : 在类加载初始化的时候就主动创建实例,如饿汉式单例; 50 | * 延迟加载 : 等到真正使用的时候才去创建实例,不用时不去主动创建,如懒汉式单例。 51 | 52 | 53 | 54 | # 实现 55 | 56 | ## 懒汉式 57 | 58 | 懒汉式是一种线程不安全,且延迟加载的实现方式;如果没有加锁 synchronized,所以严格意义上它并不算单例模式。这里分别实现以下: 59 | 60 | ### 不安全型懒汉式 61 | 62 | **线程不安全,且立即加载的实现方式,**这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。 63 | 64 | ```java 65 | public class Singleton1 { 66 | private static Singleton1 instance; 67 | private Singleton1() {} 68 | public static Singleton1 getInstance() { 69 | if (instance == null) { 70 | instance = new Singleton1(); 71 | } 72 | return instance; 73 | } 74 | } 75 | ``` 76 | 77 | **安全型懒汉式** 78 | 79 | **线程安全,且延迟加载的实现方式,**这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。 80 | 81 | **优点**:第一次调用才初始化,避免内存浪费。 82 | 83 | **缺点**:必须加锁 synchronized 才能保证单例,但加锁会影响效率。 84 | 85 | ```java 86 | public class Singleton2 { 87 | private static Singleton2 instance; 88 | private Singleton2() {} 89 | public static synchronized Singleton2 getInstance() { 90 | if (instance == null) { 91 | instance = new Singleton2(); 92 | } 93 | return instance; 94 | } 95 | } 96 | ``` 97 | 98 | ## 饿汉式 99 | 100 | **线程安全,且立即加载的实现方式**,这种方式比较常用,但容易产生垃圾对象。 101 | 102 | 优点:没有加锁,执行效率会提高。 103 | 104 | 缺点:类加载时就初始化,浪费内存。 105 | 106 | 它基于 classloader 机制避免了多线程的同步问题,不过,instance 在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用 getInstance 方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化 instance 显然没有达到 lazy loading 的效果。 107 | 108 | ```java 109 | public class Singleton3 { 110 | private static Singleton3 instance = new Singleton3(); 111 | private Singleton3() {} 112 | public static Singleton3 getInstance() { 113 | return instance; 114 | } 115 | } 116 | 117 | ``` 118 | 119 | **双检索/双重校验锁** 120 | 121 | **线程安全,且延迟加载的实现方式,**这种方式采用双锁机制,安全且在多线程情况下能保持高性能。 122 | 123 | 这种方式使用到了 volatile 和 synchronized 修饰 124 | 125 | ```java 126 | public class Singleton4 { 127 | private volatile static Singleton4 instance ; 128 | private Singleton4() {} 129 | public static Singleton4 getInstance() { 130 | if (instance == null) { 131 | synchronized (Singleton4.class) { 132 | if (instance == null) { 133 | instance = new Singleton4(); 134 | } 135 | } 136 | } 137 | return instance; 138 | } 139 | } 140 | ``` 141 | 142 | **登记式/静态内部类** 143 | 144 | **线程安全,且延迟加载的实现方式,**这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。 145 | 146 | ```java 147 | public class Singleton5 { 148 | private static class SingletonHolder { 149 | private static final Singleton5 INSTANCE = new Singleton5(); 150 | } 151 | 152 | private Singleton5() {} 153 | public static final Singleton5 getInstance() { 154 | return SingletonHolder.INSTANCE; 155 | } 156 | } 157 | ``` 158 | 159 | **枚举** 160 | 161 | **线程安全,且立即加载的实现方式,**这种实现方式还没有被广泛采用,但这是实现单例模式的最佳方法。它更简洁,自动支持序列化机制,绝对防止多次实例化。 162 | 163 | JVM会保证枚举类构造方法绝对只调用一次,所以保证了对象实例的唯一性。 164 | 165 | ```java 166 | public enum SingletonEnum { 167 | INSTANCE; 168 | public SingletonEnum getInstance(){ 169 | return INSTANCE; 170 | } 171 | } 172 | ``` 173 | 174 | 完整范例; 175 | 176 | ```java 177 | class Resource{ 178 | } 179 | public enum SingletonEnum { 180 | INSTANCE; 181 | private Resource instance; 182 | SingletonEnum() { 183 | instance = new Resource(); 184 | } 185 | public Resource getInstance() { 186 | return instance; 187 | } 188 | } 189 | ``` 190 | 191 | **资料参考** 192 | 193 | * [设计模式 | 菜鸟教程](https://www.runoob.com/design-pattern/design-pattern-tutorial.html) 194 | 195 | * Head First设计模式 196 | * Effective Java -------------------------------------------------------------------------------- /Design/设计模式(4)建造者模式.md: -------------------------------------------------------------------------------- 1 | > 将一个复杂的构建与其表示相分离,使得同样的构建过程可以创建不同的表示。 2 | 3 | **主要解决:**主要解决在软件系统中,有时候面临着"一个复杂对象"的创建工作,其通常由各个部分的子对象用一定的算法构成;由于需求的变化,这个复杂对象的各个部分经常面临着剧烈的变化,但是将它们组合在一起的算法却相对稳定。 4 | 5 | **优点:** 1、建造者独立,易扩展。 2、便于控制细节风险。 6 | 7 | **缺点:** 1、产品必须有共同点,范围有限制。 2、如内部变化复杂,会有很多的建造类。 8 | 9 | **使用场景:**多个部件或者零件,都可以装配到一个对象中,但是产生的运行结果又相同。因为产品类非常复杂,或者产品类中调用顺序不同产生了不同的作用。 10 | 11 | **注意事项:**与工厂模式的区别是:建造者模式更加关注与零件装配的顺序。 12 | 13 | **角色**: 14 | 15 | 在这样的设计模式中,有以下几个角色: 16 | 17 | 1、Builder(建造者):为创建一个产品对象的各个部件指定抽象接口。 18 | 19 | 2、ConcreteBuilder(具体建造者):实现Builder的接口以构造和装配该产品的各个部件,定义并明确它所创建的表示,并提供一个检索产品的接口。 20 | 21 | 3、Director(指挥者):构造一个使用Builder接口的对象,指导构建过程。 22 | 23 | 4、Product(产品):表示被构造的复杂对象。ConcreteBuilder创建该产品的内部表示并定义它的装配过程,包含定义组成部件的类,包括将这些部件装配成最终产品的接口。 24 | 25 | **工作流程**: 26 | 27 | 1. 指挥者(Director)直接和客户(Client)进行需求沟通; 28 | 2. 沟通后指挥者将客户的需求划分为各个部件的建造请求(Builder); 29 | 3. 建造者(Builder)将建造请求委派到具体的建造者(ConcreteBuilder), 30 | 4. ConcreteBuilder(具体建造者) 负责进行产品部件的构建, 31 | 5. 最终构建成具体产品(Product); 32 | 33 | # 实现 34 | 35 | 小明去电脑城购买一套电脑配置套件,如:键盘、鼠标、显示屏、主机; 36 | 37 | 1、先定义产品抽象类,电脑 Computer.java 38 | 39 | ```java 40 | public abstract class Computer { 41 | private String monitors; 42 | private String board; 43 | protected String os; 44 | public void setMonitors(String monitors) { 45 | this.monitors = monitors; 46 | } 47 | public void setBoard(String board) { 48 | this.board = board; 49 | } 50 | public void setOs(String os) { 51 | this.os = os; 52 | } 53 | 54 | @Override 55 | public String toString() { 56 | return "Computer{" + 57 | "monitors='" + monitors + '\'' + 58 | ", board='" + board + '\'' + 59 | ", os='" + os + '\'' + 60 | '}'; 61 | } 62 | } 63 | ``` 64 | 65 | 2、创建具体产品 66 | 67 | ```java 68 | public class MacComputer extends Computer{ 69 | public MacComputer() { 70 | super.setOs("MacOS Catalina 正式版 "); 71 | } 72 | } 73 | ``` 74 | 75 | ```java 76 | public class WinComputer extends Computer { 77 | public WinComputer() { 78 | super.setOs("Windows 10 专业版 "); 79 | } 80 | } 81 | ``` 82 | 83 | 3、创建建造者抽象类 和具体实现类 84 | 85 | ```java 86 | public interface Builder { 87 | void buildMonitors(String system); 88 | void buildBoard(String board); 89 | Computer build(); 90 | } 91 | ``` 92 | 93 | ```java 94 | public class MacBuilder implements Builder { 95 | Computer computer = new MacComputer(); 96 | @Override 97 | public void buildMonitors(String monitors) { 98 | computer.setMonitors(monitors); 99 | } 100 | @Override 101 | public void buildBoard(String board) { 102 | computer.setBoard(board); 103 | } 104 | @Override 105 | public Computer build() { 106 | return computer; 107 | } 108 | } 109 | ``` 110 | 111 | ```java 112 | public class WinBuilder implements Builder { 113 | Computer computer = new WinComputer(); 114 | @Override 115 | public void buildMonitors(String monitors) { 116 | computer.setMonitors(monitors); 117 | } 118 | @Override 119 | public void buildBoard(String board) { 120 | computer.setBoard(board); 121 | } 122 | @Override 123 | public Computer build() { 124 | return computer; 125 | } 126 | } 127 | ``` 128 | 129 | 4、创建指导者Director类 130 | 131 | ```java 132 | public class Director { 133 | // 组装过程 134 | public void construct(Builder builder, String board, String monitors) { 135 | builder.buildBoard(board); 136 | builder.buildMonitors(monitors); 137 | } 138 | } 139 | ``` 140 | 141 | 5、测试 142 | 143 | ```java 144 | public static void main(String[] args) { 145 | //装机员工 146 | Builder macBuilder = new MacBuilder(); 147 | Builder winBuilder = new WinBuilder(); 148 | //找到销售店的老板,指定装机员工 149 | Director director = new Director(); 150 | //Mac 系统组装配置 151 | director.construct(macBuilder,"i9级十核GTX1660Ti独显32G内存 ","飞利浦243V7 24英寸"); 152 | //开始装机 153 | Computer computer = macBuilder.build(); 154 | //小明查看一下配置信息,防止被骗了,输出电脑信息 155 | System.out.println(computer.toString()); 156 | 157 | 158 | //Win 系统组装配置 159 | director.construct(winBuilder,"i7级八核GTX7450独显32G内存 ","LGD 30英寸"); 160 | //开始装机 161 | computer = winBuilder.build(); 162 | //输出电脑信息 163 | System.out.println(computer.toString()); 164 | } 165 | ``` 166 | 167 | 输出: 168 | 169 | ```java 170 | Computer{monitors='飞利浦243V7 24英寸', board='i9级十核GTX1660Ti独显32G内存 ', os='MacOS Catalina 正式版 '} 171 | 172 | Computer{monitors='LGD 30英寸', board='i7级八核GTX7450独显32G内存 ', os='Windows 10 专业版 '} 173 | ``` 174 | 175 | -------------------------------------------------------------------------------- /Design/设计模式(5)原型模式.md: -------------------------------------------------------------------------------- 1 | > 用于通过拷贝创建重复的对象,同时又能保证性能 2 | 3 | **主要解决:**在运行期建立和删除原型。 4 | 5 | **优点:** 1、性能提高。 2、逃避构造函数的约束。 6 | 7 | **缺点:** 1、配备克隆方法需要对类的功能进行通盘考虑,这对于全新的类不是很难,但对于已有的类不一定很容易,特别当一个类引用不支持串行化的间接对象,或者引用含有循环结构的时候。 2、必须实现 Cloneable 接口。 8 | 9 | **Cloneable接口是一个空接口,使用Cloneable接口都不用导入包。而clone方法是属于Object对象的。如果要克隆某个对象的话必须实现Cloneable接口** 10 | 11 | **浅拷贝和深拷贝** 12 | 13 | 浅拷贝:Object类的clone方法指对拷贝对象的基本类型,对**数组,容器对象,引用对象**等不会拷贝; 14 | 15 | 深拷贝:如果实现深拷贝,必须将原型模式中的数组,容器对象,引用对象等另行拷贝; 16 | 17 | **注意**:浅拷贝实现 Cloneable,重写,深拷贝是通过实现 Serializable 读取二进制流。 18 | 19 | 20 | 21 | # 浅拷贝 22 | 23 | ```java 24 | /** 25 | * @description: 原型模式-浅拷贝 26 | * @author: husy 27 | * @date 2020/3/2 28 | */ 29 | public class Product implements Cloneable { 30 | private String name; 31 | private int[] array; 32 | 33 | public Product(String name, int[] array) { 34 | this.name = name; 35 | this.array = array; 36 | } 37 | 38 | public void setName(String name) { 39 | this.name = name; 40 | } 41 | 42 | public void setArray(int[] array) { 43 | this.array = array; 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return this.name+"--"+ Arrays.toString(this.array); 49 | } 50 | 51 | @Override 52 | protected Object clone() throws CloneNotSupportedException { 53 | return super.clone(); 54 | } 55 | } 56 | ``` 57 | 58 | Main.java 59 | 60 | ```java 61 | public static void main(String[] args) throws CloneNotSupportedException { 62 | String name = "喜洋洋"; 63 | int array[] = {1,2}; 64 | 65 | Product product1 = new Product(name,array); 66 | Product product2 =(Product) product1.clone(); 67 | System.out.println(product1.toString()); 68 | System.out.println(product2.toString()); 69 | 70 | System.out.println("-------修改字符串和数组的值,测试拷贝情况-------"); 71 | product1.setName( "灰太狼"); 72 | array[1]=4; 73 | product1.setArray(array); 74 | 75 | System.out.println(product1.toString()); 76 | System.out.println(product2.toString()); 77 | } 78 | ``` 79 | 80 | 输出: 81 | 82 | ``` 83 | 喜洋洋--[1, 2] 84 | 喜洋洋--[1, 2] 85 | -------修改字符串和数组的值,测试拷贝情况------- 86 | 灰太狼--[1, 4] 87 | 喜洋洋--[1, 4] //-->> 数组中第二个值被改变了--<< 88 | ``` 89 | 90 | 有上可知,放我们修改最后结果,克隆对象仍保留原有数组对象的引用,值随着改变而改变, 91 | 92 | 如果要想解决这种问题,以达到深拷贝的目的,可以将数组,容器对象,引用对象都进行一次拷贝,如下可以将Product 类中的 Clone 方法修改一下,将数组也拷贝一次,其他不变 93 | 94 | ```java 95 | @Override 96 | protected Object clone() throws CloneNotSupportedException { 97 | // return super.clone(); 98 | Product product = (Product) super.clone(); 99 | product.array=this.array.clone(); // 将数组也拷贝一次 100 | return product; 101 | } 102 | ``` 103 | 104 | 执行,结果如下: 105 | 106 | ``` 107 | 喜洋洋--[1, 2] 108 | 喜洋洋--[1, 2] 109 | -------修改字符串和数组的值,测试拷贝情况------- 110 | 灰太狼--[1, 4] 111 | 喜洋洋--[1, 2] 112 | ``` 113 | 114 | 最结果看出,对象所有属性都进行可控了,修改product1的属性,不会改变product2的属性 115 | 116 | # 深拷贝 117 | 118 | 创建序列化拷贝对象SerializedClone 119 | 120 | ```java 121 | public class SerializedClone { 122 | public static T clone(T obj) { 123 | T cloneObj = null; 124 | try { 125 | //写入字节流 126 | ByteArrayOutputStream out = new ByteArrayOutputStream(); 127 | ObjectOutputStream obs = new ObjectOutputStream(out); 128 | obs.writeObject(obj); 129 | obs.close(); 130 | 131 | //分配内存,写入原始对象,生成新对象 132 | ByteArrayInputStream ios = new ByteArrayInputStream(out.toByteArray()); 133 | ObjectInputStream ois = new ObjectInputStream(ios); 134 | //返回生成的新对象 135 | cloneObj = (T) ois.readObject(); 136 | ois.close(); 137 | } catch (Exception e) { 138 | e.printStackTrace(); 139 | } 140 | return cloneObj; 141 | } 142 | } 143 | ``` 144 | 145 | 测试: 146 | 147 | ```java 148 | String name1 = "喜洋洋"; 149 | int[] array1 = {10,12}; 150 | Product product3 = new Product(name1,array1); 151 | Product product4 = SerializedClone.clone(product3); 152 | System.out.println(product3.toString()); 153 | System.out.println(product4.toString()); 154 | System.out.println("-------修改属性"); 155 | array[1]=3; 156 | product1.setArray(array); 157 | System.out.println(product3.toString()); 158 | System.out.println(product4.toString()); 159 | ``` 160 | 161 | 输出如下: 162 | 163 | ``` 164 | 喜洋洋--[10, 12] 165 | 喜洋洋--[10, 12] 166 | -------修改属性 167 | 喜洋洋--[10, 12] 168 | 喜洋洋--[10, 12] 169 | ``` 170 | 171 | 序列化拷贝并不会因原型对象的属性值改变而发生变化 -------------------------------------------------------------------------------- /Experience/Mybatis中条件判断带数字的字符串.md: -------------------------------------------------------------------------------- 1 | 在mybatis中,会默认把字符串类型的数字改为数字类型:如下![img](Mybatis中条件判断带数字的字符串/clipboard.png) 2 | 3 | 4 | 5 | 所以:要想判断数字类型的字符串,需要进行如下修改![](Mybatis中条件判断带数字的字符串/clipboard.png) -------------------------------------------------------------------------------- /Experience/Mybatis中条件判断带数字的字符串/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Experience/Mybatis中条件判断带数字的字符串/clipboard.png -------------------------------------------------------------------------------- /Experience/性能优化(2)MySQL模糊查询/1578033488870.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Experience/性能优化(2)MySQL模糊查询/1578033488870.png -------------------------------------------------------------------------------- /Experience/性能优化(2)MySQL模糊查询/1578035852164.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Experience/性能优化(2)MySQL模糊查询/1578035852164.png -------------------------------------------------------------------------------- /Experience/性能优化(2)MySQL模糊查询/数据量大小.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Experience/性能优化(2)MySQL模糊查询/数据量大小.png -------------------------------------------------------------------------------- /Experience/性能优化(2)MySQL模糊查询优化.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 关于MySQL模糊查询有优化问题,网络上如下几种方案: 4 | 5 | * 模糊查询修改为后缀模糊查询 6 | * 使用LOCATE(substr,str,pos)方法 7 | * 使用POSITION(substr IN field)方法 8 | * 使用INSTR(str,substr)方法 9 | 10 | 这里测试一下真假 11 | 12 | 13 | 14 | # LOCATE、POSITION、INSTR 15 | 16 | **环境准备** 17 | 18 | MySQL 版本:8.0.16 19 | 20 | 搜索引擎:InnoDB 21 | 22 | 数据库表结构 : 23 | 24 | ```sql 25 | CREATE TABLE `user` ( 26 | `id` VARCHAR(50) NOT NULL, # 考虑特殊情况使用 UUID 主键 27 | `name` VARCHAR(30) NOT NULL, 28 | `create_time` TIMESTAMP NOT NULL, 29 | PRIMARY KEY (`id`), 30 | INDEX `idx_name` (`name`) 31 | ) 32 | COLLATE='utf8mb4_0900_ai_ci' 33 | ENGINE=InnoDB 34 | ; 35 | ``` 36 | 37 | 数据量大小:4900002 38 | 39 | ![](./性能优化(2)MySQL模糊查询/数据量大小.png) 40 | 41 | 当前系统CPU 、磁盘IO状态: 42 | 43 | ![](./性能优化(2)MySQL模糊查询//1578033488870.png) 44 | 45 | 46 | 47 | 模糊查询SQL执行3次的结果: 48 | 49 | ```sql 50 | SELECT * FROM `user` WHERE `name` LIKE '%躬%'; 51 | /* 影响到的行: 0 Found rows: 9,525 查询: 0.328 sec*/ 52 | /* 影响到的行: 0 Found rows: 9,525 查询: 0.281 sec*/ 53 | /* 影响到的行: 0 Found rows: 9,525 查询: 0.282 sec*/ 54 | ``` 55 | 56 | 可以看出平均需要 3 s 57 | 58 | 59 | 60 | 使用后缀模糊查询 61 | 62 | ```sql 63 | SELECT * FROM `user` WHERE `name` LIKE '躬%'; 64 | /* 影响到的行: 0 Found rows: 1,453 查询: 0.094 sec. */ 65 | /* 影响到的行: 0 Found rows: 1,453 查询: 0.078 sec. */ 66 | /* 影响到的行: 0 Found rows: 1,453 查询: 0.079 sec. */ 67 | ``` 68 | 69 | 以上可以看出 SQL语句可以使用了索引,搜索的效率大大的提高了! 70 | 71 | 但是,我们在做模糊查询的时候,非特定情况,这种前缀查询并不能满足需求,所以,并不合适所有的模糊查询 72 | 73 | 74 | 75 | 而使用其他函数呢? 76 | 77 | ![1578035852164](./性能优化(2)MySQL模糊查询/1578035852164.png) 78 | 79 | 80 | 81 | 可以看出 LOCATE、POSITION、INSTR并不能有效的提高查询效率。 82 | 83 | 84 | 85 | 具体怎么优化模糊查询的SQL,小编至今还没找到良好的处理方式,如果你知道,麻烦留言指点:pray::pray::pray: -------------------------------------------------------------------------------- /JVM/JVM(1)内存模型.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # JVM内存分布 4 | 5 | ![JVM 内存](./JVM(1)内存模型/clipboard-1578317326416.png) 6 | 7 | **JVM 内存区域主要分为:** 8 | 9 | * 线程私有区域【**程序计数器、虚拟机栈、本地方法区**】 10 | * 线程共享区域【**JAVA 堆、方法区**】 11 | * 直接内存。 12 | 13 | **线程私有数据区域生命周期与线程相同,依赖用户线程的启动/结束 而 创建/销毁** 14 | 15 | **线程共享区域随虚拟机的启动/关闭而创建/销毁。线程共享区域随虚拟机的启动/关闭而创建/销毁。** 16 | 17 | 18 | 19 | 20 | 21 | ![内存分布](./JVM(1)内存模型/clipboard-1578317375718.png) 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | # 堆(Heap-线程共享) 30 | 31 | **是被线程共享的一块内存区域,创建的对象和数组都保存在 Java 堆内存中**,也是垃圾收集器进行垃圾收集的最重要的内存区域。 32 | 33 | 由于现代 VM 采用**分代收集算法**,因此 Java 堆从 GC 的角度还可以细分为: **新生代**(*Eden 区*、*From Survivor 区*和 *To Survivor 区*)和**老年代。** 34 | 35 | **JDK8 时字符串池和类的静态变量放入 java 堆中** 36 | 37 | 38 | 39 | **JVM 运行时内存** 40 | 41 | Java 堆从 GC 的角度还可以细分为: **新生代**(*Eden 区*、*From Survivor 区*和 *To Survivor 区*)和**老年代**。 42 | 43 | ![img](./JVM(1)内存模型/clipboard.png) 44 | 45 | 46 | 47 | ## 新生代 48 | 49 | 是用来存放新生的对象。一般占据堆的 1/3 空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。 50 | 51 | **1. Eden 区** 52 | 53 | Java 新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。当 Eden区内存不够的时候就会触发 MinorGC,对新生代区进行一次垃圾回收。 54 | 55 | **2. ServivorFrom** 56 | 57 | 上一次 GC 的幸存者,作为这一次 GC 的被扫描者。 58 | 59 | **3. ServivorTo** 60 | 61 | 保留了一次 MinorGC 过程中的幸存者。 62 | 63 | 64 | 65 | ## **老年代** 66 | 67 | 主要存放应用程序中生命周期长的内存对象。 68 | 69 | 老年代的对象比较稳定,所以 **MajorGC** 不会频繁执行。在进行 **MajorGC 前一般都先进行了一次 MinorGC**,使得有新生代的对象晋身入老年代,**导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时**也会提前触发一次 MajorGC 进行垃圾回收腾出空间。 70 | 71 | MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出 `OOM(Out of Memory)`异常。 72 | 73 | ## 永久代 74 | 75 | 指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域,它和和存放实例的区域不同,**GC 不会在主程序运行期对永久区域进行清理**。所以这也导致了永久代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。 76 | 77 | 78 | 79 | # 方法区(线程共享) 80 | 81 | 和堆区一样,别名 Non-heap (**非堆**), 又被称为**永久代(Permanent Generation)**,**线程共享**,用于**存储被 JVM 加载的类信息**、**常量**、**静态变量**、**即时编译器编译后的代码**等数据. 82 | 83 | **运行时常量池**(Runtime Constant Pool)是方法区的一部分。Class 文件中除了有类的版本、字段、方法、接口等描述等信息外,还有一项信息是**常量池:用于存放编译期生成的各种字面量和符号引用**,这部分内容将在**类加载后**存放到方法区的运行时常量池中。 84 | 85 | 86 | 87 | HotSpot VM把GC分代收集扩展至方法区,即**使用Java堆的永久代来实现方法区**,这样 HotSpot 的垃圾收集器就可以像管理 Java 堆一样管理这部分内存,而不必为方法区开发专门的内存管理器(**永久代的内存回收的主要目标是针对常量池的回收和类型的卸载**,因此收益一般很小)。 88 | 89 | 90 | 91 | # Metaspace(元空间) 92 | 93 | **在 Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代**。 94 | 95 | 元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:**元空间并不在虚拟机中,而是使用本地内存**。因此,默认情况下,元空间的大小仅受本地内存限制。 96 | 97 | **类的元数据放入 native memory,字符串池和类的静态变量放入 java 堆中**,这样可以加载多少类的元数据就不再由 MaxPermSize 控制,而由系统的实际可用空间来控制。 98 | 99 | 100 | 101 | # 虚拟机栈(线程私有) 102 | 103 | 虚拟机栈是描述java方法执行的内存模型,其特点如下: 104 | 105 | * 每个方法在执行的同时都会创建一个**栈帧**(Stack Frame)用于存储局部变量、操作数栈、动态链接、方法出口等信息。 106 | * 每一个方法从调用直至执行完成的过程,就对应着一个栈帧在虚拟机栈中入栈到出栈的过程。 107 | * **线程私有;生命周期与线程相同** 108 | 109 | 110 | 111 | **栈帧( Frame)** 112 | 113 | 是用来存储数据和部分过程结果的数据结构,同时也被用来处理动态链接(Dynamic Linking)、 方法返回值和异常分派( Dispatch Exception)。栈帧随着方法调用而创建,随着方法结束而销毁——无论方法是正常完成还是异常完成(抛出了在方法内未被捕获的异常)都算作方法结束。 114 | 115 | 116 | 117 | **局部变量表** 118 | 119 | * 存储编译期可知的各种 **基本数据类型、对象引用类型**(引用指针或句柄)和 **returnAddress类型**(指向了一条字节码指令的地址); 120 | * 在编译期完成内存分配,当内存不足时,会抛出两种异常:SOF 异常、OOM异常;**SOF 异常** `(StackOverflowError)`:线程请求的栈深度大于虚拟机允许的深度时抛出;**OOM异常** `(OutOfMemoryError)`:无法申请到足够内存时抛出 121 | 122 | 123 | 124 | 125 | 126 | # 本地方法区(线程私有) 127 | 128 | 本地方法区和 Java Stack 作用类似,区别是虚拟机栈为执行 Java 方法服务,而本地方法栈则为Native 方法服务,如果一个 VM 实现使用 C-linkage 模型来支持 Native 调用,那么该栈将会是一个C 栈,但 HotSpot VM 直接就把本地方法栈和虚拟机栈合二为一。 129 | 130 | 也会抛出两种异常:SOF 异常、OOM异常 131 | 132 | 133 | 134 | # 程序计数器(线程私有) 135 | 136 | 一块较小的内存空间,**是当前线程所执行的字节码的行号指示器**,每条线程都要有一个独立的程序计数器,这类内存也称为 ”线程私有“ 内存。 137 | 138 | 正在执行 java 方法的话,计数器记录的是虚拟机字节码指令的地址(当前指令的地址)。如果还是 Native 方法,则为空。 139 | 140 | 这个内存区域是唯一一个在虚拟机中没有规定任何 OutOfMemoryError 情况的区域。 141 | 142 | 143 | 144 | 145 | 146 | # 内存分配策略 147 | 148 | Java 程序运行时的内存分配策略有三种 149 | 150 | * 静态分配:静态存储区(也称方法区),静态数据、全局 static 数据和常量 151 | * 栈式分配:栈区,方法体内的局部变量(其中包括基础数据类型、对象的引用) 152 | * 堆式分配:堆区,new 出来的内存,也就是对象的实例 153 | 154 | 155 | 156 | ## 堆内存分配策略 157 | 158 | Eden区存活对象进入Survivor区(Eden肯定会被清空),**大对象(长字符串或数组,byte[] 就是典型)进入直接进入老年代;如果Survivor区无法提供足够的内存,则通过分配担保机制提前进入老年代** 159 | 160 | * Survivor区中存活年龄**大于等于15**的对象直接进入老年代(每次Minor GC对象年龄加1) 161 | * Survivor区**同年龄的对象大小总和大于Survivor空间的一半时**,其他年龄大于或等于该年龄的对象直接进入老年代,年龄不必等到15 162 | * 当发生MinorGC时,**survivor空间不够时**,需要老年代分配担保,让survivor无法容纳的对象进入老年代 163 | * 年轻代空间回收称作 Minor GC ,发生频繁,老年代的垃圾回收称作 Full GC/Major GC 164 | 165 | 166 | 167 | **Minor GC** :年轻代进行的垃圾回收,非常频繁,一把回收速度较快 168 | 169 | **Major GC**:老年代进行的垃圾回收,发生一次MajorGC至少伴随一次Minor GC,一般比Minor GC慢10倍 170 | 171 | **Full GC**:整个堆内存进行垃圾回收,很多时候是Major GC 172 | 173 | 174 | 175 | **MinorGC 的过程(复制->清空->互换)采用复制算法**。 176 | 177 | 对象创建时,会在Eden区分配内存,Eden区内存不够,触发**Minor GC**(年轻代的垃圾回收) 178 | 179 | * **1:eden、servicorFrom 复制到** **ServicorTo,年龄+1** 180 | 181 | 首先,把 Eden 和 ServivorFrom 区域中存活的对象复制到 ServicorTo 区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不够位置了就放到老年区); 182 | 183 | * **2:清空 eden、servicorFrom** 184 | 185 | 然后,清空 Eden 和 ServicorFrom 中的对象; 186 | 187 | * **3:ServicorTo 和 ServicorFrom 互换** 188 | 189 | 最后,ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom区。 190 | 191 | 192 | 193 | 194 | 195 | **Full GC 的触发条件:** 196 | 197 | * 调用System.gc(), 建议虚拟机执行 Full GC,不一定正在执行,不推荐 198 | * 老年代不足时,常见场景大对象、长期存活的对象直接进入老年代时内存不足,导致频繁GC 199 | * 为 survivor 的空间担保失败。 200 | 201 | 202 | 203 | **永久代主要回收:废弃常量和无用的类**,废弃常量和无用的类的判断方式: 204 | 205 | * **废弃常量:** 该常量没有任何对象进行引用,就会被回收。 206 | * **无用的类:** 该类的所有实例都已经被回收,该类的ClassLoader已经被回收,该类的Class对象没有被引用,无法完成通过反射访问该类 207 | 208 | 209 | 210 | -------------------------------------------------------------------------------- /JVM/JVM(1)内存模型/clipboard-1578317326416.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(1)内存模型/clipboard-1578317326416.png -------------------------------------------------------------------------------- /JVM/JVM(1)内存模型/clipboard-1578317375718.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(1)内存模型/clipboard-1578317375718.png -------------------------------------------------------------------------------- /JVM/JVM(1)内存模型/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(1)内存模型/clipboard.png -------------------------------------------------------------------------------- /JVM/JVM(2)类的加载.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | # 类加载机制 8 | 9 | 在 jvm 中,Java类的加载过程分为5个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这5个过程。 10 | 11 | ![加载过程](./JVM(2)类的加载/clipboard.png) 12 | 13 | 14 | 15 | ## 加载 16 | 17 | **这个阶段会在内存中生成一个代表这个类的 `java.lang.Class` 对象,作为方法区这个类的各种数据的入口** 18 | 19 | 注意这里不一定非得要从一个 Class 文件获取,这里既可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类) 20 | 21 | **此过程完成 3 件事** 22 | 23 | * **通过全限定名获取此类的二进制字节流** 24 | * 将字节流所代表的**静态存储结构转化为方法区的运行时数据结构** 25 | * 在内存中生成此类的Class对象(Hotspot虚拟机,class对象存储在方法区),作为方法区这个类的各种数据访问入口 26 | 27 | **总结:获取二进制字节流,类的静态信息存储至方法区,在内存中生成一个class类对象** 28 | 29 | 30 | 31 | ## 验证 32 | 33 | 这一阶段的主要目的是为了**确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求**,并且不会危害虚拟机自身的安全。 34 | 35 | 大致分 4 阶段:文件格式验证、元数据验证、字节码验证、符号引用验证 36 | 37 | 38 | 39 | ## 准备 40 | 41 | 正式为类变量分配内存并设置类变量的初始值阶段,即**在方法区中分配这些变量所使用的内存空间** 42 | 43 | **数据类型默认零值,final修饰过的直接赋值** 44 | 45 | 比如一个类变量定义为: 46 | 47 | ```java 48 | public static int v = 8080; 49 | ``` 50 | 51 | 实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080,将 v 赋值为 8080 的 put static 指令是程序被编译后,存放于类构造器方法之中。 52 | 53 | ```java 54 | public static final int v = 8080; 55 | ``` 56 | 57 | 在编译阶段会为 v 生成 ConstantValue 属性,在**准备阶段虚拟机会根据 ConstantValue 属性将 v 赋值为 8080**。 58 | 59 | 60 | 61 | ## 解析 62 | 63 | **解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程** 64 | 65 | 符号引用就是 class 文件中的:1. CONSTANT_Class_info、2. CONSTANT_Field_info、3. CONSTANT_Method_info 等类型的常量。 66 | 67 | **符号引用:引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同同**,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中。 68 | 69 | **直接引用:是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。**如果有了直接引用,那引用的目标必定已经在内存中存在。 70 | 71 | 72 | 73 | ## 初始化 74 | 75 | 初始化阶段是类加载最后一个阶段。到了初始阶段,**才开始真正执行类中定义的 Java 程序代码**。就是执行类构造器()的方法过程, 76 | 77 | 方法是由编译器自动收集类中的类变量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子方法执行之前,父类的方法已经执行完毕**,如果一个类中没有对静态变量赋值也没有静态语句块,那么编译器可以不为这个类生成()方法。** 78 | 79 | **卸载** 80 | 81 | JVM中的Class只有满足以下三个条件,才能被GC回收,也就是该Class被卸载(unload): 82 | 83 | * 该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例。 84 | * 加载该类的ClassLoader已经被GC。 85 | * 该类的java.lang.Class 对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法 86 | 87 | 88 | 89 | # 类初始化的时机 90 | 91 | * 使用new 实例化对象时 92 | * 调用静态变量时(常量除外)、静态方法 93 | * 通过反射调用 94 | * 初始化一个类如果父类没有初始化,先触发父类的初始化 95 | * 执行main方法的启动类 96 | 97 | 98 | 99 | **注意以下几种情况不会执行类初始化**: 100 | 101 | 1. 通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。 102 | 103 | 2. 定义对象数组,不会触发该类的初始化。 104 | 105 | 3. 常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。 106 | 107 | 4. 通过类名获取 Class 对象,不会触发类的初始化。 108 | 109 | 5. 通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。 110 | 111 | 6. 通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作。 112 | 113 | 114 | 115 | **接口和类的的初始化区别:**只需要真正使用到的父接口初始化,不需要所有父接口都初始化 116 | 117 | 118 | 119 | # 类加载方式 120 | 121 | **静态加载**:编译时刻加载的类是静态加载类,new关键字来实例对象,编译时执行,由JVM初始化加载 122 | 123 | **动态加载**:运行时刻加载的类是动态加载类,反射方式加载就是动态加载;通过Class.forName()方法动态加载或者通过ClassLoader.loadClass()方法动态加载 124 | 125 | **Class.forName()和ClassLoader.loadClass()的区别** 126 | 127 | * Class.forName:将类的.class文件加载到jvm中之外,还会对类进行解释,执行类中的static块。 128 | * classloader只将.class文件加载到jvm中,不会执行static中的内容,只有在newInstance才会去执行static块。 129 | * Class.forName(name,initialize,loader)带参数也可控制是否加载static块。并且只有调用了newInstance()方法采用调用构造函数,创建类的对象。 130 | 131 | 132 | 133 | # 类加载器 134 | 135 | JVM 提供了 3 种类加载器: 136 | 137 | * **启动类加载器(Bootstrap ClassLoader):** 138 | 139 | 负责加载 JAVA_HOME\lib 目录中的,或通过-bootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类 140 | 141 | * **扩展类加载器(Extension ClassLoader)** 142 | 143 | 负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。 144 | 145 | * **应用程序类加载器(Application ClassLoader)** 146 | 147 | 负责加载用户路径(classpath)上的类库。JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader实现自定义的类加载器。 148 | 149 | ![双亲委派](./JVM(2)类的加载/clipboard-1578402208674.png) 150 | 151 | 152 | 153 | **双亲委派** 154 | 155 | **当一个类收到了类加载请求,他首先不会尝试自己去加载这个类,而是把这个请求委派给父类去完成**,每一个层次类加载器都是如此,因此所有的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈自己无法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试自己去加载。 156 | 157 | 158 | 159 | **双亲委派模型优点:** 160 | 161 | ==避免同一个类被多次加载;每个加载器只能加载自己范围内的类,保证java程序的稳定运行==,比如加载位于 rt.jar 包中的类 java.lang.Object,不管是哪个加载器加载这个类,最终都是委托给顶层的启动类加载器进行加载,这样就**保证了使用不同的类加载器最终得到的都是同样一个 Object 对象**。 162 | 163 | 164 | 165 | **思考:可以不可以自己写个String类?** 166 | 167 | 答案:不可以,因为根据类加载的双亲委派机制,会去加载父类,父类发现冲突了String就不再加载了; -------------------------------------------------------------------------------- /JVM/JVM(2)类的加载/clipboard-1578402208674.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(2)类的加载/clipboard-1578402208674.png -------------------------------------------------------------------------------- /JVM/JVM(2)类的加载/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(2)类的加载/clipboard.png -------------------------------------------------------------------------------- /JVM/JVM(3)GC回收机制/clipboard-1578404417512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(3)GC回收机制/clipboard-1578404417512.png -------------------------------------------------------------------------------- /JVM/JVM(3)GC回收机制/clipboard-1578404442145.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(3)GC回收机制/clipboard-1578404442145.png -------------------------------------------------------------------------------- /JVM/JVM(3)GC回收机制/clipboard-1578404472763.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(3)GC回收机制/clipboard-1578404472763.png -------------------------------------------------------------------------------- /JVM/JVM(3)GC回收机制/clipboard-1578404707683.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(3)GC回收机制/clipboard-1578404707683.png -------------------------------------------------------------------------------- /JVM/JVM(3)GC回收机制/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/JVM/JVM(3)GC回收机制/clipboard.png -------------------------------------------------------------------------------- /Java/Java-基础篇(10)泛型.md: -------------------------------------------------------------------------------- 1 | 在 Java中泛型占具着很重要的地位,在面向对象编程及各种设计模式中有非常广泛的应用。 2 | 3 | **泛型的本质是参数化类型**,也就是说将类型由原来的具体的类型转化为类似于方法中的变量参数形式 4 | 5 | 泛型有三种常用的使用方式:**泛型类**,**泛型接口**和**泛型方法**。 6 | 7 | 8 | 9 | **泛型的标记符:** 10 | 11 | - E - Element (在集合中使用,因为集合中存放的是元素) 12 | - T - Type(Java 类) 13 | - K - Key(键) 14 | 15 | - V - Value(值) 16 | 17 | - N - Number(数值类型) 18 | 19 | - ? - 表示不确定的java类型 20 | 21 | - S、U、V - 2nd、3rd、4th types 22 | 23 | 24 | 25 | # 泛型类 26 | 27 | 指具有一个或多个类型变量的类,泛型类定义如下: 28 | 29 | ```java 30 | //此处T可以随便写为任意标识,常见的如T、E、K、V等形式的参数常用于表示泛型 31 | class 类名 <泛型标识>{ 32 | /*(这里的泛型标识标识成员变量类型),由外部指定 */ 33 | private 泛型标识 变量名称; 34 | ..... 35 | 36 | //get、set 省略 37 | 38 | } 39 | ``` 40 | 41 | **注意**:泛型的类型参数只能是引用类型,不能是基本数据类型 42 | 43 | 44 | 45 | 举例: 46 | 47 | ```java 48 | public class Generic{ 49 | private T key; 50 | public Generic(T key) { 51 | this.key = key; 52 | } 53 | public T getKey(){ 54 | return key; 55 | } 56 | public void setKey(T key){ 57 | this.key = key; 58 | } 59 | } 60 | ``` 61 | 62 | 使用如下: 63 | 64 | ```java 65 | Generic genericInteger = new Generic(123456); 66 | ``` 67 | 68 | 69 | 70 | 71 | 72 | # 泛型接口 73 | 74 | 泛型接口与泛型类的定义及使用基本相同。泛型接口常被用在各种类的生产器中,泛型接口格式如下: 75 | 76 | ```java 77 | public interface 类名 <泛型标识> { 78 | public 泛型标识 getKey(); 79 | } 80 | ``` 81 | 82 | 范例: 83 | 84 | ```java 85 | public interface IGeneric { 86 | public T getKey() { 87 | return null; 88 | } 89 | } 90 | ``` 91 | 92 | 93 | 94 | # 泛型方法 95 | 96 | 在 Java 中,泛型方法是返回对象为泛型,如: 97 | 98 | ```java 99 | //声明了一个泛型T,表明这是一个泛型方法 100 | //这个T可以出现在这个泛型方法的任意位置. 101 | public T genericMethod(Class tClass){ 102 | T instance = tClass.newInstance(); 103 | return instance; 104 | } 105 | ``` 106 | 107 | 108 | 109 | 以下方式不正确: 110 | 111 | ```java 112 | //虽然我们声明了,也表明了这是一个可以处理泛型的类型的泛型方法。 113 | //但是只声明了泛型类型T,并未声明泛型类型E,因此编译器并不知道该如何处理E这个类型。 114 | //编译器会为提示错误信息:"UnKnown class 'E' " 115 | public T showKeyName(Generic container){ 116 | ... 117 | } 118 | ``` 119 | 120 | ```java 121 | //T这个类型并未项目中声明过,因此编译器也不知道该如何编译这个类, 122 | //所以编译器会为提示错误信息:"UnKnown class 'T' " 123 | public void showkey(T genericObj){ 124 | ... 125 | } 126 | ``` 127 | 128 | -------------------------------------------------------------------------------- /Java/Java-基础篇(1)总纲.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ​ Java 篇章中,一般我们面试时都会考察我们掌握的基础点,看是否基础牢固,决定了我们是不是能进一步的交流,如果一个人的基础都牢固,那面试官肯定不要你。 4 | 5 | 以下我们从以下几个方便来巩固以下我们的技术点: 6 | 7 | * 三大特性和六大原则 8 | * 关键字 9 | * 数据类型 10 | * 类初始化 11 | * 逻辑运算 12 | * 异常 13 | * 反射 14 | 15 | ![Java基础](./Java-基础篇(1)总纲/Java基础.png) 16 | 17 | **章节整理目录:** 18 | 19 | - [Java-基础篇(1)总纲](./Java-基础篇(1)总纲.md) 20 | 21 | - [Java-基础篇(2)三大特性和六大原则](./Java-基础篇(2)三大特性和六大原则.md) 22 | 23 | - [Java-基础篇(3)常用关键字特性](./Java-基础篇(3)常用关键字特性.md) 24 | 25 | - [Java-基础篇(4)数据类型](./Java-基础篇(4)数据类型.md) 26 | 27 | - [Java-基础篇(5)类加载和初始化](./Java-基础篇(5)类加载和初始化.md) 28 | 29 | - [Java-基础篇(6)逻辑运算](./Java-基础篇(6)逻辑运算.md) 30 | 31 | - [Java-基础篇(7)反射](./Java-基础篇(7)反射.md) 32 | 33 | - [Java-基础篇(8)异常](./Java-基础篇(8)异常.md) 34 | 35 | - [Java-基础篇(9)内部类](./Java-基础篇(9)内部类.md) 36 | 37 | - [Java-基础篇(10)泛型](./Java-基础篇(10)泛型.md) 38 | 39 | 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /Java/Java-基础篇(1)总纲/Java基础.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-基础篇(1)总纲/Java基础.png -------------------------------------------------------------------------------- /Java/Java-基础篇(2)三大特性和六大原则.md: -------------------------------------------------------------------------------- 1 | # 三大特性 2 | 3 | 在 Java 编程中三大特性指的是**封装、继承、多态** 4 | 5 | * 封装:封装把一个对象的属性私有化,同时提供一些可以被外界访问的属性的方法,如果属性不想被外界访问,我们大可不必提供方法给外界访问优点:减少耦合,代码重用,减轻维护 6 | * 继承:它可以使用现有类的所有功能,并在无需重新编写原来的类的情况下对这些功能进行扩展。 7 | * 多态:指允许不同类的对象对同一消息做出响应。 8 | 9 | 10 | 11 | --- 12 | 13 | ## 多态 14 | 15 | 多态一般分为编译时多态和运行时多态,编译时主要指方法的重载;运行时主要指程序中定义的对象引用所指向的具体类型在运行期间才确定 16 | 17 | **运行时多态有三个条件:继承、覆盖和重写、向上转型(父类引用指向子类对象)** 18 | 19 | --- 20 | 21 | ## 方法重载和重写区别 22 | 23 | 重写:**发生在继承类中,方法名和参数列表相同**,重写有以下三个限制: 24 | 25 | * 子类方法的访问权限必须大于等于父类方法; 26 | * 子类方法的返回类型必须是父类方法返回类型或为其子类型。 27 | * 子类方法抛出的异常类型必须是父类抛出异常类型或为其子类型。 28 | 29 | 重载:**发生在同一个类中,方法名相同,参数列表不同(个数、类型、顺序),与权限修饰、返回值类型、抛出异常无关** 30 | 31 | 32 | 33 | **注意**:构造器是不可以被重写的,但是能重载。 34 | 35 | 构造方法有哪些特性? 36 | 37 | 1. 名字与类名相同。 38 | 2. 没有返回值,但不能用void声明构造函数。 39 | 3. 生成类的对象时自动执行,无需调用。 40 | 41 | --- 42 | 43 | # 六大原则 44 | 45 | 1. **开闭原则**:对扩展开发放,对修改关闭,要求在添加新功能时不需要修改代码,符合开闭原则最典型的设计模式是装饰者模式 46 | 2. **单一职责原则**:一个类只负责一件事,尽量使用合成/聚合的方式,而不是使用继承。 47 | 3. **里式替换原则** :任何基类可以出现的地方,子类一定可以出现。 48 | 4. **依赖倒转原则**:依赖于抽象而不依赖于具体 49 | 5. **接口隔离原则**:使用多个隔离的接口,比使用单个接口要好 ,不应该强迫客户依赖于它们不用的方法。 50 | 6. **迪米特法则**:一个软件实体应当尽可能少地与其他实体发生相互作用。 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /Java/Java-基础篇(3)常用关键字特性.md: -------------------------------------------------------------------------------- 1 | 本章中主要了解一下我们在开发过程中常用,也必须掌握的一些特殊关键字的作用。 2 | 3 | 4 | 5 | # 访问权限 6 | 7 | 在Java中有4中访问权限的修饰符:**private**、**default**((默认一般省略)、**public**、**protected**。一般用于对类或类中的成员(字段以及方法)加上访问修饰符 8 | 9 | 权限的主要作用范围:同一个类中、同一个包下、父子类、不同的包 10 | 11 | 可被修饰对象:类和成员变量;类可见表示其它类可以用这个类创建实例对象;成员可见表示其它类可以用这个类的实例对象访问到该成员。 12 | 13 | **4种修饰符的权限范围:** 14 | 15 | > * private:指”私有的”。被其修饰的属性以及方法只能被该类的对象访问,其子类不能访问,更不能允许跨包访问 16 | > * default:即不加任何访问修饰符,通常称为“默认访问权限“或者“包访问权限”。该模式下,只允许在同一个包中进行访问。 17 | > * protected: 介于public 和 private 之间的一种访问修饰符,一般称之为“保护访问权限”。被其修饰的属性以及方法只能被类本身的方法及子类访问,即使子类在不同的包中也可以访问。 18 | > * public: Java语言中访问限制最宽的修饰符,一般称之为“公共的”。被其修饰的类、属性以及方法不仅可以跨类访问,而且允许跨包访问。 19 | 20 | | 修饰符 | 同类 | 同包 | 子类 | 不同包非子类 | 21 | | --------- | ---- | :--- | ---- | ------------ | 22 | | private | √ | × | × | × | 23 | | default | √ | √ | × | × | 24 | | protected | √ | √ | √ | × | 25 | | public | √ | √ | √ | √ | 26 | 27 | 从上表中我们很容易看出,权限范围从小到大依次为:**private < default < protected < public** 28 | 29 | ------------------------------------------------ 30 | 31 | 32 | # final 和 static 33 | 34 | ## final 35 | 36 | 在Java中,final关键字可以用来修饰类、方法和变量(包括成员变量和局部变量) 37 | 38 | * **修饰变量**:表示常量,对于基本类型,final 使数值不变;对于引用类型,final 使引用地址不变,但对象本身的属性是可以被修改的。 39 | * **修饰方法**:不能被子类的方法重写,但可以被继承,**不能修饰构造方法**。。 40 | * **修饰类** :该不能被继承,没有子类,final类中的方法默认是final的。Java中的String类就是一个final类 41 | 42 | 43 | 44 | ## static 45 | 46 | 在Java语言中,static 可以用来修饰成员变量和成员方法,当然也可以是静态代码块 47 | 48 | * **静态变量**:又称为类变量,该类的所有实例都共享本类的静态变量,且在内存中只存在一份 49 | * **静态方法**:在类加载的时候就存在了,它不依赖于任何实例,只能访问所属类的静态字段和静态方法,方法中不能有 this 和 super 关键字(此时可能没有实例)。 50 | * **静态语句块**:在类初始化时运行一次。 51 | * **静态内部类**:非静态内部类依赖于外部类的实例,而静态内部类不需要。静态内部类不能访问外部类的非静态的变量和方法。 52 | 53 | 54 | 55 | **使用时注意:** 56 | 57 | 1. 静态变量,静态方法可以通过类名直接访问 58 | 2. 初始化顺序:静态变量和静态语句块优先于实例变量和普通语句块,静态变量和静态语句块的初始化顺序取决于它们在代码中的顺序。(此处不演示,在类初始化篇章中演示) 59 | 60 | 61 | 62 | **问:在一个静态方法内调用一个非静态成员为什么是非法的?** 63 | 64 | 由于静态方法可以不通过对象进行调用,因此在静态方法里,不能调用其他非静态变量,也不可以访问非静态变量成员。 65 | 66 | 67 | 68 | ## **成员变量、静态变量、局部变量的区别** 69 | 70 | 从生命周期比较: 71 | 72 | * 静态变量可以被对象调用,也可以被类名调用。以static关键字申明的变量,其独立在对象之外,有许多对象共享的变量。在对象产生之前产生,存在于**方法区静态区中**。 73 | * 成员变量只能被对象调用。随着对象创建而存在,随对象销毁而销毁。存在于**堆栈内存中** 74 | * 局部变量在方法或语句块中申明的变量,生命周期只在定义的{}之中,不能跨方法或语句块使用。 75 | 76 | 从访问权限比较: 77 | 78 | * **静态变量称为对象的共享数据**,成员变量可以称为对象的特有数据,局部变量为方法所有 79 | * 成员变量可以被 public,private,static 等修饰符所修饰,而局部变量不能被访问控制修饰符及 static 所修饰;但是,成员变量和局部变量都能被 final 所修饰。 80 | 81 | --- 82 | 83 | 84 | 85 | # abstract 和 interface 86 | 87 | ## abstract 88 | 89 | 在 Java 中 abstract 即抽象,一般使用 `abstract` 关键字修饰的类或方法 90 | 91 | 修饰的类时 92 | 93 | > 1. 不能被实例化,需要继承抽象类才能实例化其子类。 94 | > 2. 访问权限可以使用`public`、`private`、`protected`,其表达形式为:(public)abstract class 类名{} 95 | > 3. 抽象类不能使用final关键字修饰,因为final修饰的类是无法被继承 96 | > 4. 可以定义构造方法、静态方法、普通方法;非抽象的普通成员变量、静态成员变量 97 | 98 | 修饰的方法时 99 | 100 | > 1. 含有该抽象方法的类必须定义为抽象类,但抽象类可以没有抽象方法。 101 | > 2. 访问权限可以使用`public`、`default`、`protected`,不能为`private`,因为抽象方法必须被子类实现(覆写),而private权限对于子类来 说是不能访问的,所以就会产生矛盾, 102 | > 3. 不能用static修饰,因为没有主体 103 | 104 | ```java 105 | public abstract class MyAbstract { 106 | public String name="小米"; 107 | private static int price= 1800; 108 | 109 | MyAbstract(String name){ 110 | this.name = name; 111 | } 112 | 113 | public void test() { 114 | System.out.println(name); 115 | } 116 | public static void fun() { 117 | System.out.println(price); 118 | } 119 | public abstract void print();//权限不能为 private 120 | } 121 | ``` 122 | 123 | 124 | 125 | ## interface 126 | 127 | 在 Java中 interface 即接口,是抽象类的延伸,在 Java 8 之前,它可以看成是一个完全抽象的类,Java 8 开始,接口也可以拥有`default`的方法实现,是因为不支持默认方法的接口的维护成本太高 128 | 129 | > 1. 接口的方法访问权限只能为 `public `,Java 8可以为`default`,但是必须有方法体 130 | > 2. 接口的方法默认`public abstract` 也可以由 static 修饰 131 | > 3. 接口的方法可以定义为 `public static` ,但是必须有方法体,且只能有接口类名调用 132 | > 4. 成员变量默认为`public staic final` 133 | 134 | ```java 135 | public interface MyInterface { 136 | int price = 1800; 137 | 138 | void outName(); 139 | 140 | default void print() { 141 | System.out.println("MyInterface print: default Method"); 142 | } 143 | 144 | public static void price() { 145 | System.out.println("MyInterface price="+price); 146 | } 147 | } 148 | public class MyInterfaceImpl implements MyInterface { 149 | @Override 150 | public void outName() { 151 | System.out.println("I'm a MyInterfaceImpl"); 152 | } 153 | public static void main(String[] args) { 154 | MyInterface my = new MyInterfaceImpl(); 155 | my.outName(); 156 | my.print(); 157 | // MyInterfaceImpl.print();// 实现类类名调用时, 提示编译错误 158 | MyInterface.price(); 159 | } 160 | } 161 | 162 | ``` 163 | 164 | 165 | 166 | ## abstract 和 interface 的区别 167 | 168 | **从定义分析** 169 | 170 | * 抽象类和接口都不能直接实例化;抽象方法必须由子类来进行重写 171 | * 抽象类单继承,接口多实现 172 | * 抽象类可有构造方法,普通成员变量,非抽象的普通方法,静态方法 173 | * 抽象类的抽象方法访问权限可以为:public、protected 、default 174 | * 接口中变量类型默认public staic final, 175 | * 接口中普通方法默认public abstract,没有具体实现 176 | * jdk1.8 中接口可有**静态方法和default(有方法体)方法** 177 | 178 | **从应用场合分析** 179 | 180 | * 接口:需要将一组类视为单一的类,而调用者只通过接口来与这组类发生联系。 181 | * 抽象类:1、在既需要统一的接口,又需要实例变量或缺省的方法的情况下就可以使用它;2、定义了一组接口,但又不想强迫每个实现类都必须实现所有的接口 -------------------------------------------------------------------------------- /Java/Java-基础篇(6)逻辑运算/image-20200101202719891.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-基础篇(6)逻辑运算/image-20200101202719891.png -------------------------------------------------------------------------------- /Java/Java-基础篇(7)反射.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 反射定义 4 | 5 | 在 Java 中的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法; 6 | 7 | 这种动态获取信息以及动态调用对象方法的功能成为 Java 语言的反射机制。 8 | 9 | 10 | 11 | `Class` 和 `java.lang.reflect` 一起对反射提供了支持,`java.lang.reflect` 类库主要包含了以下三个类: 12 | 13 | - Field 类:表示类的成员变量,可以用来获取和设置类之中的属性值。 14 | - Method 类:表示类的方法,它可以用来获取类中的方法信息或者执行方法。 15 | - Constructor 类: 表示类的构造方法。 16 | 17 | 18 | 19 | **反射的优点:** 20 | 21 | - **能够运行时动态获取类的实例,大大提高系统的灵活性和扩展性。** 22 | - 与Java动态编译相结合,可以实现无比强大的功能 23 | 24 | **反射的缺点:** 25 | 26 | - **性能开销** :反射涉及了动态类型的解析,所以 JVM 无法对这些代码进行优化。因此,反射操作的效率要比那些非反射操作低得多。 27 | - **安全限制** :使用反射技术要求程序必须在一个没有安全限制的环境中运行。如果一个程序必须在有安全限制的环境中运行,如 Applet,那么这就是个问题了。 28 | - **内部暴露** :破坏了类的封装性,可以通过反射获取这个类的私有方法和属性 29 | 30 | 31 | 32 | # 反射实现方式 33 | 34 | **在 Java 中反射有 3 中获取 `Class` 的实现方式**,如下: 35 | 36 | 1. 调用某个对象的 `getClass()`方法 37 | 38 | ```java 39 | Person p=new Person(); 40 | Class clazz=p.getClass(); 41 | ``` 42 | 43 | 2. 调用某个类的 class 属性来获取该类对应的 Class 对象 44 | 45 | ```java 46 | Class clazz=Person.class; 47 | ``` 48 | 49 | 3. 使用 Class 类中的 `forName()`静态方法是最安全、性能最好,最常用的一种方式 50 | 51 | ```java 52 | Class clazz=Class.forName("类的全路径"); 53 | ``` 54 | 55 | 56 | 57 | * Class 创建对象的 2 种方式 58 | 59 | 1. 使用 Class 对象的 `newInstance()` 60 | 2. 先使用 Class 对象获取指定的 Constructor 对象,再调用 Constructor 对象的 newInstance() 61 | 62 | 63 | 64 | # 实战演练 65 | 66 | ```java 67 | //获取 Person 类的 Class 对象 68 | Class clazz=Class.forName("reflection.Person"); 69 | //获取 Person 类的所有方法信息 70 | Method[] method=clazz.getDeclaredMethods(); 71 | for(Method m:method){ 72 | System.out.println(m.toString()); 73 | } 74 | //获取 Person 类的所有成员属性信息 75 | Field[] field=clazz.getDeclaredFields(); 76 | for(Field f:field){ 77 | System.out.println(f.toString()); 78 | } 79 | //获取 Person 类的所有构造方法信息 80 | Constructor[] constructor=clazz.getDeclaredConstructors(); 81 | for(Constructor c:constructor){ 82 | System.out.println(c.toString()); 83 | } 84 | //使用.newInstane 方法创建对象 85 | Person p=(Person) clazz.newInstance(); 86 | //获取构造方法并创建对象 87 | Constructor c=clazz.getDeclaredConstructor(String.class,String.class,int.class); 88 | //创建对象并设置属性 89 | Person p1=(Person) c.newInstance("李四","男",20); 90 | ``` 91 | 92 | -------------------------------------------------------------------------------- /Java/Java-基础篇(8)异常.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # 异常分类 6 | 7 | Throwable 是 Java 语言中所有错误或异常的超类。下一层分为 **Error** 和 **Exception** 8 | 9 | * **Error**:用来表示 JVM 无法处理的错误,是指 java 运行时系统的内部错误和资源耗尽错误。应用程序不会抛出该类对象不便于也不需要捕获,属于不可检查时异常。常见的比如`OutOfMemoryError`、`StackOverflowError`都是Error的子类。 10 | 11 | * **Exception(RuntimeException、CheckedException)**: Exception 又 有 两 个 分 支 , 一 个 是 运 行 时 异 常 RuntimeException , 一 个 是CheckedException。 12 | 13 | ![](./Java-基础篇(8)异常/untitled%20diagram.png) 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | # Exception 22 | 23 | **运行时异常 RuntimeException** : 其与子类都是未检查的异常,如 `NullPointerException` 、 `ClassCastException` ;是那些可能在 Java 虚拟机正常运行期间抛出的异常的超类。 如果出现 `RuntimeException`,那么一定是程序员的错误. 24 | 25 | **检查异常 CheckedException**:如 I/O 错误导致的 `IOException`、`SQLException`,一般是外部错误,这种异常都发生在编译阶段,Java 编译器会**强制程序去捕获此类异常**,即会出现要求程序进行 try catch,如:`Thread.sleep()`、`IOException`、`SQLException`等以及用户自定义的Exception异常 26 | 27 | **抛出异常有 3 种形式,一是 throw,一个 throws,还有一种系统自动抛异常。** 28 | 29 | 30 | 31 | ## Throw 和 throws 的区别: 32 | 33 | 1. throws 用在函数上,后面跟的是异常类,可以跟多个;而 throw 用在函数内,后面跟的是异常对象。 34 | 2. throws 用来声明异常,让调用者只知道该功能可能出现的问题,可以给出预先的处理方式;throw 抛出具体的问题对象,执行到 throw,功能就已经结束了,跳转到调用者,并将具体的问题对象抛给调用者。也就是说 throw 语句独立存在时,下面不要定义其他语句,因为执行不到。 35 | 3. throws 表示出现异常的一种可能性,并不一定会发生这些异常;throw 则是抛出了异常,执行 throw 则一定抛出了某种异常对象。 36 | 37 | 38 | 39 | ## 常见Exception 40 | 41 | **运行时异常**(RuntimeException) 42 | 43 | - NullPointerException(空指针异常) 44 | - ArrayIndexOutOfBoundsException(数组下标越界) 45 | - ClassNotFoundException(找不到类) 46 | - ArithmeticException(算术异常) 47 | 48 | 49 | 50 | **检查异常 (CheckedException)** 51 | 52 | - IOException:输入输出异常 53 | - SQLException:操作数据库异常 54 | - FileNotFoundException:文件未找到异常 55 | - NoSuchMethodException:方法未找到异常 56 | 57 | 58 | 59 | # Throwable类常用方法 60 | 61 | - **public string getMessage()**:返回异常发生时的详细信息 62 | - **public string toString()**:返回异常发生时的简要描述 63 | - **public string getLocalizedMessage()**:返回异常对象的本地化信息。使用Throwable的子类覆盖这个方法,可以声称本地化信息。如果子类没有覆盖该方法,则该方法返回的信息与getMessage()返回的结果相同 64 | - **public void printStackTrace()**:在控制台上打印Throwable对象封装的异常信息 -------------------------------------------------------------------------------- /Java/Java-基础篇(8)异常/untitled diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-基础篇(8)异常/untitled diagram.png -------------------------------------------------------------------------------- /Java/Java-基础篇(9)内部类.md: -------------------------------------------------------------------------------- 1 | Java 类根据定义的方式不同,内部类分为**静态内部类**,**成员内部类**,**局部内部类**,**匿名内部类**四种。 2 | 3 | 4 | 5 | # 静态或成员内部类 6 | 7 | 定义在类内部的静态类,就是静态内部类。非静态类就是成员内部类。**成员内部类不能定义静态方法和变量(final 修饰的除外)。** 8 | 9 | ```java 10 | public class Out { 11 | private static int a; 12 | private int b; 13 | public static class Inner { 14 | public void print() { 15 | System.out.println(a); 16 | } 17 | } 18 | } 19 | ``` 20 | 21 | 1. 静态内部类可以访问外部类所有的静态变量和方法,即使是 private 的也一样。 22 | 2. 静态内部类和一般类一致,可以定义静态变量、方法,构造方法等。 23 | 3. 其它类使用静态内部类需要使用“外部类.静态内部类”方式,如下所示:Out.Inner inner =new Out.Inner();inner.print(); 24 | 4. Java集合类HashMap内部就有一个静态内部类Entry。Entry是HashMap存放元素的抽象,HashMap 内部维护 Entry 数组用了存放元素,但是 Entry 对使用者是透明的。像这种和外部类关系密切的,且不依赖外部类实例的,都可以使用静态内部类。 25 | 26 | 27 | 28 | # 局部内部类 29 | 30 | **局部内部类是指定义在方法中的类**,如果一个类只在某个方法中使用,则可以考虑使用局部类 31 | 32 | ```java 33 | public class Out { 34 | private static int a; 35 | private int b; 36 | public void test(final int c) { 37 | final int d = 1; 38 | class Inner { 39 | public void print() { 40 | System.out.println(c); 41 | } 42 | } 43 | } 44 | } 45 | ``` 46 | 47 | 48 | 49 | # 匿名内部类 50 | 51 | 匿名内部类也就是没有名字的内部类,使用匿名内部类还有个前提条件:**必须继承一个父类或实现一个接口** 52 | 53 | 最常用的情况就是在多线程的实现上,因为要实现多线程必须继承Thread类或是继承Runnable接口 54 | 55 | ```java 56 | public class Demo { 57 | public static void main(String[] args) { 58 | Thread t = new Thread() { 59 | public void run() { 60 | for (int i = 1; i <= 5; i++) { 61 | System.out.print(i + " "); 62 | } 63 | } 64 | }; 65 | t.start(); 66 | } 67 | } 68 | ``` 69 | 70 | -------------------------------------------------------------------------------- /Java/Java-集合篇(1)集合.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 在 Java 中,集合类是一个用来存放对象的容器,它们都存放于 `java.util` 包中, 6 | 7 | 主要有 3 种:set(集)、list(列表包含 Queue)和 map(映射)。 8 | 9 | 1. Collection:Collection 是集合 List、Set、Queue 的最基本的接口。 10 | 11 | 2. Map:是映射表的基础接口 12 | 3. Iterator:迭代器,可以通过迭代器遍历集合中的数据 13 | 14 | ![集合类关系](./Java-集合篇(1)集合/clipboard-1578149517475.png) 15 | 16 | 17 | 18 | ## Collection 接口 19 | 20 | * **List** :在 Java 的 List 是非常常用的数据类型。**List 是有序的 Collection**。Java List 一共三个实现类:分别是 `ArrayList`、`Vector` 和 `LinkedList`。 21 | 22 | * **Set**:注重独一无二的性质,**值不能重复**。用于存储无序元素,存入和取出的顺序不一定相同;但凡是都有例外,TreeSet(自然序) 和 LinkedHashSet(插入顺序) 就是有序的;**如果想要让两个不同的对象视为相等的,就必须覆盖 Object 的 hashCode 方法和 equals 方法。** 23 | 24 | * **Queue**:队列,具备先进先出或者先进后出的特点;常见**LinkedList**:可以用它来实现双向队列。**PriorityQueue**:基于堆结构实现,可以用它来实现优先队列。 25 | 26 | ![Collection集合特点](./Java-集合篇(1)集合/clipboard-1578149500539.png) 27 | 28 | ## Map 接口 29 | 30 | Map 是通过键值对存储,其键名唯一,键值可重复 31 | 32 | ![Map 集合特点](./Java-集合篇(1)集合/clipboard-1578149461477.png) 33 | 34 | ## Iterator 35 | 36 | Collection 继承了 Iterable 接口,其中的 iterator() 方法能够产生一个 Iterator 对象,通过这个对象就可以迭代遍历 Collection 中的元素。 37 | 38 | 从 JDK 1.5 之后可以使用 foreach 方法来遍历实现了 Iterable 接口的聚合对象。 39 | 40 | **特点**: 41 | 42 | * 迭代遍历过程中,禁止改变容器大小,如:add、remove操作,会抛出`ConcurrentModificationException`异常 43 | * 快速失败机制(fail-fast):当多个线程对Collection进行操作时,若其中某一个线程通过 Iterator 遍历集合时,该集合的内容被其他线程所改变,则会抛出`ConcurrentModificationException`异常。 44 | 45 | ### Fail-Fast 原因 46 | 47 | * 是迭代器在遍历时直接访问集合中的内容,并且在遍历过程中使用一个 modCount 变量(用来记录 ArrayList 结构发生变化的次数)。集合在被遍历期间如果内容发生变化,就会改变 modCount 的值。 48 | * 结构发生变化是指添加或者删除至少一个元素的所有操作,或者是调整内部数组的大小,仅仅只是设置元素的值不算结构发生变化。 49 | * 每当迭代器使用 hashNext()/next() 遍历下一个元素之前,都会检测 modCount 变量是否为 expectedModCount 值,是的话就返回遍历;否则抛出异常,终止遍历。 50 | 51 | 52 | 53 | ### 快速失败(fail-fast)和安全失败(fail-safe) 54 | 55 | * HashMap、ArrayList 这些集合类,这些在 java.util 包的集合类就都是快速失败的;而 `java.util.concurrent` 包下的类都是安全失败,比如:ConcurrentHashMap。 56 | * 快速失败在遍历时`直接访问`集合中的内容 57 | * 安全失败在遍历时不是直接在集合内容上访问的,而是`先复制`原有集合内容,在拷贝的集合上进行遍历。 58 | 59 | 60 | 61 | **快速失败(fail-fast)解决办法** 62 | 63 | * 通过`java.util.concurrent`集合包下的相应类(`CopyOnWriteArrayList`是自己实现Iterator)去处理,则不会产生`fast-fail`事件。 64 | * `CopyOnWriteArrayList`类是复制了数组,不是直接操作原数组 65 | 66 | 67 | 68 | ### for与foreach的对比 69 | 70 | * **foreach使用的是迭代器循环,for是使用索引下标检索** 71 | * 需要**循环数组结构**的数据时,建议**使用普通for循环**,因为for循环采用下标访问,对于数组结构的数据来说,采用下标访问比较好。 72 | * 需要**循环链表结构**的数据时,**一定不要使用普通for循环**,这种做法很糟糕,数据量大的时候有可能会导致系统崩溃。 73 | 74 | ```java 75 | //使用方式 76 | Iterator it = list.iterator(); 77 | while(it.hasNext()){ 78 |  Object obj= it.next(); 79 | } 80 | ``` 81 | 82 | **Iterator 接口包含 4 个方法** 83 | 84 | ```java 85 | E next ( ) ; 86 | boolean hasNext (); 87 | void remove () ; 88 | default void forEachRemaining ( Consumer < ? super E > action ) ; 89 | ``` 90 | 91 | ## 多线程下的集合安全 92 | 93 | 由于集合大多数是线程不安全的,可采用如下方式处理 94 | 95 | * 使用加锁机制:synchronized、Lock 96 | * 使用 volalite 修饰 97 | * 使用 ThreadLocal 对象 98 | * 使用集合工具类 Collections,通过如下方法操作,常用有:`synchronizedCollection`、`synchronizedList(List list)`、`synchronizedMap(Map m)`、`synchronizedSet(Set s)` 99 | * 使用`java.util.concurrent`提供的并发集合对象,其提供了映射 、 有序集和队列的高效实现 ,常用有:**ConcurrentHashMap**、**CopyOnWriteArrayList**、**CopyOnWriteArraySet**、`ConcurrentSkipListMap(SkipList:跳表)`、`ConcurrentSkipListSet`、`ConcurrentLinkedQueue` 100 | 101 | 注释 : 有些应用使用庞大的并发散列映射 , 这些映射太过庞大 , 以至于无法用 size 方法得到它的大小,因为这个方法只能返回 int。 对于一个包含超过20 亿条目的映射该如何处理 **JavaSE 8 引入了一个 mappingCount 方法可以把大小作为 long 返回。** 102 | 103 | 104 | 105 | 106 | -------------------------------------------------------------------------------- /Java/Java-集合篇(1)集合/clipboard-1578149461477.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(1)集合/clipboard-1578149461477.png -------------------------------------------------------------------------------- /Java/Java-集合篇(1)集合/clipboard-1578149500539.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(1)集合/clipboard-1578149500539.png -------------------------------------------------------------------------------- /Java/Java-集合篇(1)集合/clipboard-1578149517475.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(1)集合/clipboard-1578149517475.png -------------------------------------------------------------------------------- /Java/Java-集合篇(3)集合之Set.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # HashSet 6 | 7 | 基于**哈希表**实现,哈希表边存放的是哈希值。是**无序存储**,其存储元素的顺序并不是按照存入时的顺序(和 List 显然不同) 而是按照哈希值来存的所以取数据也是按照哈希值取得。 8 | 9 | **HashSet 首先判断两个元素的哈希值,如果哈希值一样,接着会比较equals 方法 如果 equls 结果为 true ,HashSet 就视为同一个元素。如果 equals 为 false 就不是同一个元素。** 10 | 11 | 12 | 13 | **问题**:哈希值相同 equals 为 false 的元素是怎么存储呢? 14 | 15 | HashSet 通过 hashCode 值来确定元素在内存中的位置。一个 hashCode 位置上可以存放多个元素。底层其实是数组+单向链表实现,如图: 16 | 17 | ![hashcode实现](./Java-集合篇(3)集合之Set/clipboard-1578149491166.png) 18 | 19 | 20 | 21 | **hashCode 作用** 22 | 23 | * hash 算法可以直接根据元素的 hashCode 值计算出该元素的存储位置从而快速定位该元素 24 | * 如果两个对象相同,就是适用于 equals() 方法,那么这两个对象的hashCode一定要相同 25 | 26 | 27 | 28 | 29 | 30 | # TreeSet 31 | 32 | 基于**红黑树**实现,是使用二叉树的原理对新 `add()` 的对象按照**指定的顺序排序(升序、降序)**,每增加一个对象都会进行排序,将对象插入的二叉树指定的位置。 33 | 34 | Integer 和 String 对象都可以进行默认的 TreeSet 排序,而自定义类的对象是不可以的,自己定义的类必须**实现 Comparable 接口,并且覆写相应的 compareTo()函数**,才可以正常使用。 35 | 36 | 37 | 38 | # LinkHashSet 39 | 40 | **通过继承与 HashSet、又基于 LinkedHashMap 来实现的。加双向链表维持元素的顺序,有序(`插入顺序`)** 41 | 42 | 底层使用 LinkedHashMap 来保存所有元素,它继承与 HashSet,其所有的方法操作上又与 HashSet 相同 43 | 44 | -------------------------------------------------------------------------------- /Java/Java-集合篇(3)集合之Set/clipboard-1578149491166.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(3)集合之Set/clipboard-1578149491166.png -------------------------------------------------------------------------------- /Java/Java-集合篇(4)集合之Queue.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ### 正在整理中,敬请期待!! -------------------------------------------------------------------------------- /Java/Java-集合篇(5)集合之Map.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## HashMap 4 | 5 | 基于**哈希表实现**。底层用**数组+单向链表**(1.8增加了**黑红树**)存储,内部包含了一个 Node 类型的数组 table。 每个 Node 节点有4个属性:`hash、key、value 、next` 6 | 7 | HashMap 非线程安全。如果需要满足线程安全,可以用 Collections 的 synchronizedMap 方法使HashMap 具有线程安全的能力,或者使用 ConcurrentHashMap。 8 | 9 | 10 | 11 | **HashMap为什么不直接使用数组,还需要使用HashSet呢?** 12 | 13 | 因为数组元素的索引是连续的,而数组的长度是固定的,无法自由增加数组的长度。而HashSet就不一样了,HashSet采用每个元素的hashCode值来计算其存储位置,从而可以自由增加长度,并可以根据元素的hashCode值来访问元素。 14 | 15 | **HashMap线程不安全原因** 16 | 17 | * 多线程下新增可能会被覆盖:两个线程在单链上插入同一个位置时会被覆盖 18 | * 扩容易丢失数据:多个线程同时扩容时,最终只有最后一个线程生成的新数组被赋给table变量,其他线程的均会丢失。 19 | 20 | * **HashMap 死循环原理**,可能在链表上,链表最后一个元素指向了链表表头,形成循环 21 | 22 | 23 | 24 | 25 | 26 | ## HashMap存储方式 27 | 28 | HashMap 是以 数组 + 双向链表 + 红黑树 29 | 30 | * 不发生 hash 碰撞时以数组存储 31 | * 发生 hash 碰撞,且链表长度小于 8 ,以链表存储 32 | * 发生 hash 碰撞,且链表长度大于等于 8 ,转为红黑树存储,(JDK 1.8 新增的 ) 33 | 34 | 所谓 **“拉链法”** 就是:将链表和数组相结合。也就是说创建一个链表数组,数组中每一格就是一个链表。若遇到哈希冲突,则将冲突的值加到链表中即可 35 | 36 | 37 | 38 | **JAVA7 实现** 39 | 40 | HashMap 里面是一个数组,然后数组中每个元素是一个单向链表。下图中,每个绿色的实体是嵌套类 Entry 的实例,时间复杂度为 **O(n)**,取决于链表的长度。 41 | 42 | 1. capacity:当前数组容量,始终保持 2^n,可以扩容,**扩容后数组大小为当前的 2 倍**。 43 | 44 | 2. loadFactor:负载因子,默认为 0.75。 45 | 46 | 3. threshold:扩容的阈值,等于 capacity * loadFactor 47 | 48 | ![Java7 HashMap 存储机制](./Java-集合篇(5)集合之Map/clipboard-1578149439454.png) 49 | 50 | 51 | 52 | **JAVA8实现** 53 | 54 | Java8 对 HashMap 进行了一些修改,最大的不同就是利用了红黑树,所以其由 **数组+链表+红黑树** 组成。 55 | 56 | 在 Java8 中,当发生 hash 碰撞的时候,以链表的形式进行存储,当链表中的元素超过了 **8 个**以后,会将链表转换为红黑树,在这些位置进行查找的时候可以降低**时间复杂度为 O(logN)**。 57 | 58 | ![Java8 HashMap 存储机制](./Java-集合篇(5)集合之Map/clipboard-1578149421429.png) 59 | 60 | 61 | 62 | ## ConcurrentHashMap 63 | 64 | 整个 ConcurrentHashMap 由一个个 Segment 组成,Segment 代表”部分“或”一段“的意思,所以很多地方都会将其描述为**分段锁,线程安全(Segment 继承 ReentrantLock 加锁)** 65 | 66 | 并行度(默认 16),也就是说 ConcurrentHashMap 有 16 个 Segments,,所以理论上,这个时候,最多可以同时支持 16 个线程并发写 67 | 68 | ![Java8 ConcurrentHashMap 存储](./Java-集合篇(5)集合之Map/clipboard-1578149537394.png) 69 | 70 | 71 | 72 | 73 | 74 | ## HashTable 75 | 76 | **是线程安全的**,任一时间只有一个线程能写 Hashtable,并发性不如 ConcurrentHashMap,因为 ConcurrentHashMap 引入了分段锁。 77 | 78 | Hashtable 不建议在新代码中使用,不需要线程安全的场合可以用 HashMap 替换,需要线程安全的场合可以用 ConcurrentHashMap 替换。 79 | 80 | 81 | 82 | 83 | 84 | ## TreeMap 85 | 86 | **可排序**,TreeMap 实现 SortedMap 接口,能够把它保存的记录根据键排序,**默认是按键值的升序排序**,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时,得到的记录是排过序的。如果使用排序的映射,建议使用 TreeMap。 87 | 88 | 89 | 90 | ## LinkHashMap(记录插入顺序) 91 | 92 | LinkedHashMap 是 HashMap 的一个子类,保存了记录的插入顺序,在用 Iterator 遍历 93 | 94 | LinkedHashMap 时,先得到的记录肯定是先插入的,也可以在构造时带参数,按照访问次序排序。 95 | 96 | 97 | 98 | ## Map遍历方式 99 | 100 | * 通过Map#keySet() 获取键值Set集合,遍历 key 获取 value 101 | * 通过Map#entrySet().iterator() 获取迭代器对象iterator ,通过迭代器获取 Entry对象。然后获取key和value 102 | * 通过Map#entrySet() 获取Entry对象集合,遍历Entry对象集合,通过Entry 获取key和value 103 | * 通过Map#values() 获取所有的 value 集合,但不能遍历key 104 | 105 | ```java 106 | // 1. 通过Map.keySet遍历key和value 107 | for (String key : hashmap.keySet()){ 108 | System.out.println("key: "+ key + "; value: " + hashmap.get(key)); 109 | } 110 | 111 | //2. 通过Map.entrySet使用iterator遍历key和value: 112 | Iterator> it = hashmap.entrySet().iterator(); 113 | while (it.hasNext()){ 114 | Map.Entry entry = it.next(); 115 | System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue()); 116 | } 117 | 118 | //3. 通过Map.entrySet遍历key和value 119 | for(Map.Entry entry : hashmap.entrySet()){ 120 | System.out.println("key: "+ entry.getKey() + "; value: " + entry.getValue()); 121 | } 122 | 123 | //4. 通过Map.values()遍历所有的value,但不能遍历key 124 | for (String value : hashmap.values()) { 125 | System.out.println("value: "+value); 126 | } 127 | ``` 128 | 129 | -------------------------------------------------------------------------------- /Java/Java-集合篇(5)集合之Map/clipboard-1578149421429.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(5)集合之Map/clipboard-1578149421429.png -------------------------------------------------------------------------------- /Java/Java-集合篇(5)集合之Map/clipboard-1578149439454.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(5)集合之Map/clipboard-1578149439454.png -------------------------------------------------------------------------------- /Java/Java-集合篇(5)集合之Map/clipboard-1578149537394.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/Java-集合篇(5)集合之Map/clipboard-1578149537394.png -------------------------------------------------------------------------------- /Java/多线程(1)基础.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | ## 进程与线程 6 | 7 | **进程**:资源分配和调度单位 8 | 9 | * 操作系统进行资源分配的最小单位,资源包括:CPU、内存空间、磁盘等 10 | * 同一个进程中的多个线程共享该进程中的全部资源(堆和方法区资源) 11 | * 进程之间是相互独立的 12 | 13 | **线程**:线程是CPU调度的最小单位,必须依赖进程而存在 14 | 15 | 16 | 17 | ## 线程上下文切换 18 | 19 | 巧妙地利用了时间片轮转的方式,CPU 给每个任务都服务一定的时间,然后把当前任务的状态保存下来,在加载下一任务的状态后,继续服务下一任务,任务的状态保存及再加载, 这段过程就叫做上下文切换。时间片轮转的方式使多个任务在同一颗 CPU 上执行变成了可能。 20 | 21 | **上下文**:是指某一时间点 CPU 寄存器和程序计数器的内容 22 | 23 | 24 | 25 | **引起线程上下文切换的原因** 26 | 27 | * 当前执行任务的时间片用完之后,系统 CPU 正常调度下一个任务; 28 | * 当前执行任务碰到 IO 阻塞,调度器将此任务挂起,继续下一任务; 29 | * 多个任务抢占锁资源,当前任务没有抢到锁资源,被调度器挂起,继续下一任务; 30 | * 用户代码挂起当前任务,让出 CPU 时间; 31 | * 硬件中断; 32 | 33 | 34 | 35 | **线程让出 cpu 的情况** 36 | 37 | * 当前运行线程主动放弃 CPU,JVM 暂时放弃 CPU 操作(基于时间片轮转调度的 JVM 操作系统不会让线程永久放弃 CPU,或者说放弃本次时间片的执行权),例如调用 yield()方法。 38 | * 当前运行线程因为某些原因进入阻塞状态,例如阻塞在 I/O 上。 39 | * 当前运行线程结束,即运行完 run()方法里面的任务。 40 | 41 | 42 | 43 | ## 线程调度方式 44 | 45 | * **抢占式调度**:抢占式调度指的是每条线程执行的时间、线程的切换都由系统控制。在这种机制下,一个线程的堵塞不会导致整个进程堵塞。 46 | * **协同式调度**:协同式调度指某一线程执行完后主动通知系统切换到另一线程上执行,这种模式就像接力赛一样,但它有一个致命弱点:如果一个线程编 47 | 48 | 写有问题,运行到一半就一直堵塞,那么可能导致整个系统崩溃。 49 | 50 | JVM 的线程调度实现(抢占式调度) 51 | 52 | ## 串行、并行与并发 53 | 54 | 串行:在同一时间一个人只能做一件事的情况下,一个人交替做着做多件事 55 | 56 | 并行:在同一时间一个人同时做多件事,如左后开弓一般 57 | 58 | 并发:在同一时间多个人抢着做同一件事,如竞争一个位置 59 | 60 | ## 同步和异步 61 | 62 | 同步:发送一个请求,等待返回,然后再发送下一个请求。 63 | 64 | 异步:发送一个请求,不等待返回,随时可以在发送下一个请求。 65 | 66 | ## 吞吐量TPS 67 | 68 | 吞吐量表示在单位时间内通过某个网络或接口的数据量 69 | 70 | ## 高并发 71 | 72 | 优点:充分利用CPU、加快响应用户的时间、是代码模块化、异步化、简单化 73 | 74 | 缺点:发生线程安全问题、容易死循环 75 | 76 | **高并发与分布式** 77 | 78 | * **高并发**:指并发在单个资源个体的情况下实现达到最大资源利用价值,如:1个服务器4个CPU*4核,那么并行为16,高并发则利用多线程技术,可能实现160个 79 | * **分布式**:当来了 1 万个并发时,原来资源满足不了,就并行的再多开几个资源服务器。说白了就是多找几个服务器写作完成。常见架构有Hadoop、Hbase、Zookeeper、Redis 80 | -------------------------------------------------------------------------------- /Java/多线程(2)Thread/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/多线程(2)Thread/clipboard.png -------------------------------------------------------------------------------- /Java/多线程(2)Thread/untitled_diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Java/多线程(2)Thread/untitled_diagram.png -------------------------------------------------------------------------------- /Java/多线程(3)线程池.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # 线程池的组成 6 | 7 | 一般的线程池主要分为以下 4 个组成部分: 8 | 9 | 1. **线程池管理器**:用于创建并管理线程池 10 | 2. **工作线程**:线程池中的线程 11 | 3. **任务接口**:每个任务必须实现的接口,用于工作线程调度其运行 12 | 4. **任务队列**:用于存放待处理的任务,提供一种缓冲机制 13 | 14 | Java 中的线程池是通过 Executor 框架实现的,该框架中用到了 Executor, xecutors,ExecutorService,ThreadPoolExecutor ,Callable 和 Future、FutureTask 这几个类。 15 | 16 | # 线程池的作用 17 | 18 | * 降低资源消耗:通过重用已经创建的线程来降低线程创建和销毁的消耗 19 | * 提高响应速度:任务到达时不需要等待线程创建就可以立即执行 20 | * 提高线程的可管理性:线程池可以统一管理、分配、调优和监控 21 | 22 | # **4** 种线程池 23 | 24 | Java 里面线程池的顶级接口是 **Executor**,但是严格意义上讲 Executor 并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是 **ExecutorService**。 25 | 26 | * **newCachedThreadPool**:创建一个可缓存线程池 ,优先使用线程池中的空闲线程,没有可用的线程时,创建一个新线程并添加到池中 27 | * **newFixedThreadPool**:创建一个 固定线程数的线程池,没有可用的线程时,新的任务需要在队列中等待待。如果在关闭前的执行期间由于失败而导致任何线程终止,那么一个新线程将代替它执行后续的任务(如果需要)。在某个线程被显式地关闭之前,池中的线程将一直存在。 28 | * **newScheduledThreadPool**:创建一个定时线程池,可延后或者定期执行。 29 | * **newSingleThreadExecutor**:创建一个单线程的线程池,这个线程池只有一个线程。这个线程池可以在线程死后(或发生异常时)重新启动一个线程来替代原来的线程继续执行下去! 30 | 31 | 主要特点为:线程复用;控制最大并发数;管理线程 32 | 33 | # 线程池原理 34 | 35 | Executor 管理多个异步任务的执行,而无需程序员显式地管理线程的生命周期。这里的异步是指多个任务的执行互不干扰,不需要进行同步操作。 36 | 37 | 这里示范一下 newScheduledThreadPool 的使用,如下: 38 | 39 | ```java 40 | public static void main(String[] args) { 41 | ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3); 42 | scheduledThreadPool.schedule(() -> System.out.println("延迟三秒"), 3, TimeUnit.SECONDS); 43 | scheduledThreadPool.scheduleAtFixedRate(() -> System.out.println("延迟 1 秒后每三秒执行一次"),1,3,TimeUnit.SECONDS); 44 | } 45 | 46 | //输出: 47 | 延迟 1 秒后每三秒执行一次 48 | 延迟三秒 49 | 延迟 1 秒后每三秒执行一次 50 | 延迟 1 秒后每三秒执行一次 51 | ``` 52 | 53 | 注意:线程池不允许使用 Executors 去创建,而是通过 ThreadPoolExecutor 的方式,这样的处理方式让写的同学更加明确线程池的运行规则,规避资源耗尽的风险。 54 | 55 | 56 | 57 | # 线程池实现过程 58 | 59 | 线程池创建线程的过程如下: 60 | 61 | ```java 62 | ExecutorService pool = Executors.newFixedThreadPool(taskSize); 63 | || 64 | \/ 65 | public static ExecutorService newFixedThreadPool(int nThreads) { 66 | return new ThreadPoolExecutor(nThreads, nThreads,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue()); 67 | } 68 | || 69 | \/ 70 | public ThreadPoolExecutor( 71 | int corePoolSize,//核心线程数 ,线程池的核心池大小,在创建线程池之后,线程池默认没有任何线程。 72 | int maximumPoolSize,//允许的 最大线程数 。maximumPoolSize肯定是大于等于corePoolSize。 73 | long keepAliveTime,//当前线程池数量超过 corePoolSize 时,多余的空闲线程的存活时间,即多少时间内会被销毁。 74 | TimeUnit unit,//keepAliveTime 的单位。 75 | BlockingQueue workQueue, 76 | ThreadFactory threadFactory,//线程工厂,用于创建线程,一般用默认的即可。 77 | RejectedExecutionHandler handler) //拒绝策略,当任务太多来不及处理,如何拒绝任务。 78 | ``` 79 | 80 | **线程池实现原理** 81 | 82 | 了解线程池具体的执行过程,可以通过ThreadPoolExecutor.execute() 分析一下 83 | 84 | ```java 85 | public void execute(Runnable command) { 86 | if (command == null) 87 | throw new NullPointerException(); 88 | int c = ctl.get(); 89 | //1.当前池中线程比核心数少,新建一个线程执行任务 90 | if (workerCountOf(c) < corePoolSize) { 91 | //新建一个线程 92 | if (addWorker(command, true)) 93 | return; 94 | c = ctl.get(); 95 | } 96 | //2.核心池已满,但任务队列未满,添加到队列中 97 | if (isRunning(c) && workQueue.offer(command)) { 98 | int recheck = ctl.get(); 99 | if (! isRunning(recheck) && remove(command)) 100 | //如果这时被关闭了,拒绝任务 101 | reject(command); 102 | else if (workerCountOf(recheck) == 0) 103 | //如果之前的线程已被销毁完,新建一个线程 104 | addWorker(null, false); 105 | } 106 | //核心池已满,队列已满,试着创建一个新线程 107 | else if (!addWorker(command, false)) 108 | //如果创建新线程失败了,说明线程池被关闭或者线程池完全满了,拒绝任务 109 | reject(command); 110 | } 111 | ``` 112 | 113 | 从上面代码可以等,线程池工作流程如下: 114 | 115 | 1. 线程池刚创建时,里面没有一个线程。任务队列是作为参数传进来的。不过,就算队列里面有任务,线程池也不会马上执行它们。 116 | 2. 当调用 execute() 方法添加一个任务时,线程池会做如下判断: 117 | * 如果正在运行的线程数量小于 corePoolSize,那么马上创建线程运行这个任务; 118 | * 如果正在运行的线程数量大于或等于 corePoolSize,那么将这个任务放入队列; 119 | * 如果这时候队列满了,而且正在运行的线程数量小于 maximumPoolSize,那么还是要创建非核心线程立刻运行这个任务; 120 | * 如果队列满了,而且正在运行的线程数量大于或等于 maximumPoolSize,那么线程池会抛出异常 RejectExecutionException。 121 | 3. 当一个线程完成任务时,它会从队列中取下一个任务来执行。 122 | 4. 当一个线程无事可做,超过一定的时间(keepAliveTime)时,线程池会判断,如果当前运行的线程数大于 corePoolSize,那么这个线程就被停掉。所以线程池的所有任务完成后,它最终会收缩到 corePoolSize 的大小。 123 | 124 | 125 | 126 | # 线程池的关闭 127 | 128 | ThreadPoolExecutor提供了两个方法,用于线程池的关闭,分别是shutdown()和shutdownNow() 129 | 130 | * **shutdown()** : **不会立即终止线程池** ,而是要等所有任务缓存队列中的任务都执行完后才终止,但再也不会接受新的任务 131 | * **shutdownNow()** : **立即终止线程池** ,并尝试打断正在执行的任务,并且清空任务缓存队列,返回尚未执行的任务 132 | 133 | # 阻塞队列 134 | 135 | BlockingQueue接口有:ArrayBlockingQueue , DelayQueue , LinkedBlockingDeque , LinkedBlockingQueue , LinkedTransferQueue , PriorityBlockingQueue , SynchronousQueue 136 | 137 | **ArrayBlockingQueue (有界队列)** :是一个基于数组结构的有界阻塞队列,此队列按 FIFO(先进先出)原则对元素进行排序。 138 | 139 | **LinkedBlockingQueue (无界队列)** :一个基于链表结构的阻塞队列,此队列按FIFO (先进先出) 排序元素,吞吐量通常要高于ArrayBlockingQueue。静态工厂方法Executors.newFixedThreadPool()使用了这个队列。 140 | 141 | **SynchronousQueue(同步队列)** : 一个不存储元素的阻塞队列。每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue,静态工厂方法Executors.newCachedThreadPool使用了这个队列。 142 | 143 | **DelayQueue(延迟队列)** :一个任务定时周期的延迟执行的队列。根据指定的执行时间从小到大排序,否则根据插入到队列的先后排序。 144 | 145 | **PriorityBlockingQueue(优先级队列)** : 一个具有优先级得无限阻塞队列。 146 | 147 | 148 | 149 | **怎么理解无界队列和有界队列** 150 | 151 | * 有界队列即长度有限,满了以后ArrayBlockingQueue会插入阻塞。 152 | * 无界队列就是里面能放无数的东西而不会因为队列长度限制被阻塞,但是可能会出现OOM异常。 153 | 154 | 155 | 156 | # 拒绝策略 157 | 158 | 线程池中的线程已经用完了,无法继续为新任务服务,同时,等待队列也已经排满了,再也塞不下新任务了。这时候我们就需要拒绝策略机制合理的处理这个问题。 159 | 160 | * AbortPolicy:直接抛出异常,阻止系统正常运行。,它将抛出RejectedExecutionException。 161 | * CallerRunsPolicy:只要线程池未关闭,该策略直接在调用者线程中,运行当前被丢弃的任务。显然这样做不会真的丢弃任务,但是,任务提交线程的性能极有可能会急剧下降。 162 | * DiscardOldestPolicy:丢弃最老的一个请求,也就是即将被执行的一个任务,并尝试再次提交当前任务。 163 | * DiscardPolicy:该策略默默地丢弃无法处理的任务,不予任何处理。如果允许任务丢失,这是最好的一种方案。 164 | 165 | 以上内置拒绝策略均实现了 RejectedExecutionHandler 接口,若以上策略仍无法满足实际需要,完全可以自己扩展 RejectedExecutionHandler 接口。 166 | 167 | 168 | 169 | 170 | 171 | -------------------------------------------------------------------------------- /Java/多线程(5)锁分类.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # 锁分类 6 | 7 | 锁的分类比较复杂,这里了解一下各类锁的 8 | 9 | ## 同步锁和互斥锁 10 | 11 | 同步是协调多个相互关联线程合作完成任务,彼此之间知道对方存在,执行顺序往往是有序的 12 | 13 | 互斥是通过竞争对资源的独占使用,彼此之间不需要知道对方的存在,执行顺序是一个乱序。 14 | 15 | 16 | 17 | ## 悲观锁和乐观锁 18 | 19 | **乐观锁**:乐观认为读多写少,遇到并发写的可能性低,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,采取在写时先读出当前版本号,然后加锁操作(比较跟上一次的版本号,如果一样则更新),如果失败则要重复读-比较-写的操作。java 中的乐观锁基本都是通过 CAS 操作实现的,CAS 是一种更新的原子操作,比较当前值跟传入值是否一样,一样则更新,否则失败。 20 | 21 | **悲观锁**:悲观认为写多,遇到并发写的可能性高,每次去拿数据的时候都认为别人会修改,所以每次在读写数据的时候都会上锁,这样别人想读写这个数据就会 block 直到拿到锁。java中的悲观锁就是Synchronized,AQS框架下的锁则是先尝试cas乐观锁去获取锁,获取不到,才会转换为悲观锁,如 RetreenLock。 22 | 23 | 24 | 25 | ## 公平锁和非公平锁 26 | 27 | **非公平锁**:加锁时不考虑排队等待问题,直接尝试获取锁,获取不到自动到队尾等待;JVM 按随机、就近原则分配锁的机制则称为不公平锁,ReentrantLock 在构造函数中提供了是否公平锁的初始化方式,ReentantLock默认为非公平锁,synchronized 是非公平锁。非公平锁实际执行的效率要远远超出公平锁,除非程序有特殊需要,否则最常用非公平锁的分配机制。 28 | 29 | **公平锁**:加锁前检查是否有排队等待的线程,优先排队等待的线程,先来先得;公平锁指的是锁的分配机制是公平的,通常先对锁提出获取请求的线程会先被分配到锁,ReentrantLock 在构造函数中提供了是否公平锁的初始化方式来定义公平锁。非公平锁性能比公平锁高 5~10 倍,因为公平锁需要在多核的情况下维护一个队列 30 | 31 | 32 | 33 | ## 共享锁和独占锁 34 | 35 | java 并发包提供的加锁模式分为独占锁和共享锁。 36 | 37 | **独占锁**:独占锁模式下,每次只能有一个线程能持有锁,ReentrantLock 就是以独占方式实现的互斥锁。独占锁是一种悲观保守的加锁策略,它避免了读/读冲突,如果某个只读线程获取锁,则其他读线程都只能等待,这种情况下就限制了不必要的并发性,因为读操作并不会影响数据的一致性 38 | 39 | **共享锁**:共享锁则允许多个线程同时获取锁,并发访问 共享资源,如:ReadWriteLock。共享锁则是一种乐观锁,它放宽了加锁策略,允许多个执行读操作的线程同时访问共享资源。 40 | 41 | 42 | 43 | ## 轻量锁和重量锁 44 | 45 | 锁的状态总共有四种:无锁状态、偏向锁、轻量级锁和重量级锁。 46 | 47 | **重量级锁**:依赖于操作系统 Mutex Lock 所实现的锁我们称之为“重量级锁”;如:Synchronized 是通过对象内部的一个叫做监视器锁(monitor)来实现的。 48 | 49 | **轻量级锁**:轻量级锁所适应的场景是线程交替执行同步块的情况,如果存在同一时间访问同一锁的情况,就会导致轻量级锁膨胀为重量级锁。 50 | 51 | **锁升级**:随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁(但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级)。 52 | 53 | 54 | 55 | ## 自旋锁 56 | 57 | 自旋锁原理非常简单,如果持有锁的线程能在很短时间内释放锁资源,那么那些等待竞争锁的线程就不需要做内核态和用户态之间的切换进入阻塞挂起状态,它们只需要等一等(自旋),等持有锁的线程释放锁后即可立即获取锁,这样就避免用户线程和内核的切换的消耗。 58 | 59 | **自旋锁的优缺点** 60 | 61 | 线程自旋是需要消耗 cup 的,说白了就是让 cup 在做无用功,如果一直获取不到锁,那线程也不能一直占用 cup 自旋做无用功,所以需要设定一个自旋等待的最大时间。如果持有锁的线程执行的时间超过自旋等待的最大时间扔没有释放锁,就会导致其它争用锁的线程在最大等待时间内还是获取不到锁,这时争用线程会停止自旋进入阻塞状态。 62 | 63 | 自旋锁尽可能的减少线程的阻塞,这对于锁的竞争不激烈,且占用锁时间非常短的代码块来说性能能大幅度的提升,因为自旋的消耗会小于线程阻塞挂起再唤醒的操作的消耗,这些操作会导致线程发生两次上下文切换! 64 | 65 | 但是如果锁的竞争激烈,或者持有锁的线程需要长时间占用锁执行同步块,这时候就不适合使用自旋锁了,因为自旋锁在获取锁前一直都是占用 cpu 做无用功,占着 XX 不 XX,同时有大量线程在竞争一个锁,会导致获取锁的时间很长,线程自旋的消耗大于线程阻塞挂起操作的消耗,其它需要 cup 的线程又不能获取到 cpu,造成 cpu 的浪费。所以这种情况下我们要关闭自旋锁; 66 | 67 | 68 | 69 | ## 可重入锁(递归锁) 70 | 71 | 可重入锁,也叫做递归锁,指的是同一线程外层函数获得锁之后 ,内层递归函数仍然有获取该锁的代码,但不受影响。在 JAVA 环境下 ReentrantLock 和 synchronized 都是 可重入锁。 72 | 73 | ## 偏向锁 74 | 75 | 偏向锁的目的是在某个线程获得锁之后,消除这个线程锁重入(CAS)的开销,看起来让这个线程得到了偏护;而偏向锁则是在只有一个线程执行同步块时进一步提高性能。 76 | 77 | ## 分段锁 78 | 79 | 分段锁也并非一种实际的锁,而是一种思想 ConcurrentHashMap 是学习分段锁的最好实践 80 | 81 | ## 锁优化 82 | 83 | * 减少锁持有时间,只用在有线程安全要求的程序上加锁, 84 | * 减小锁粒度:将大对象,拆成小对象,大大增加并行度,降低锁竞争。降低了锁的竞争,偏向锁,轻量级锁成功率才会提高。最典型的减小锁粒度的案例就是ConcurrentHashMap。 85 | * 锁分离:最常见的锁分离就是读写锁 ReadWriteLock,读写分离思想可以延伸,只要操作互不影响,锁就可以分离。比如LinkedBlockingQueue 从头部取出,从尾部放数据 86 | * 锁粗化:通常情况下,为了保证多线程间的有效并发,会要求每个线程持有锁的时间尽量短,即在使用完公共资源后,应该立即释放锁。但是,凡事都有一个度,如果对同一个锁不停的进行请求、同步和释放,其本身也会消耗系统宝贵的资源,反而不利于性能的优化 。 87 | * 锁消除:锁消除是在编译器级别的事情。在即时编译器时,如果发现不可能被共享的对象,则可以消除这些对象的锁操作,多数是因为程序员编码不规范引起。 88 | 89 | -------------------------------------------------------------------------------- /Notes/Git 命令.md: -------------------------------------------------------------------------------- 1 | # Git 命令 2 | 3 | # 下载项目 4 | 5 | 通过 `git clone` 克隆远程仓库 6 | 7 | ```shell 8 | git clone https://github.com/hsy-nfox/Job-Notes.git 9 | ``` 10 | 11 | 12 | 13 | # 提交代码 14 | 15 | ```shell 16 | git add . 17 | git commit -m "注释" 18 | git push origin master 19 | ``` 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | # 更新代码 28 | 29 | ```shell 30 | git pull # 更新, 这里需要确保不会冲突 31 | ``` 32 | 33 | 34 | 35 | 问题: 使用 `git pull` 提示如下: 36 | 37 | ```shell 38 | Already up to date. 39 | ``` 40 | 41 | 然后 使用 git status 42 | 43 | ```shell 44 | $ git status 45 | On branch master 46 | Your branch is up to date with 'origin/master'. 47 | 48 | Changes not staged for commit: 49 | (use "git add ..." to update what will be committed) 50 | (use "git checkout -- ..." to discard changes in working directory) 51 | 52 | modified: README.md 53 | modified: "java/Java\345\237\272\347\241\200.md" 54 | modified: "notes/Git \345\221\275\344\273\244.md" 55 | 56 | Untracked files: 57 | (use "git add ..." to include in what will be committed) 58 | 59 | java/Java IO.md 60 | "notes/JDK \347\211\210\346\234\254\347\211\271\346\200\247.md" 61 | 62 | no changes added to commit (use "git add" and/or "git commit -a") 63 | 64 | ``` 65 | 66 | 主要是`Your branch is up to date with 'origin/master'.` 这根本原因是版本分支的问题 67 | 68 | **解决方式** 69 | 70 | 这时候我们就需要新建一个分支 71 | 72 | ``` 73 | $ git branch newbranch 74 | ``` 75 | 76 | 然后检查分支是否创建成功 77 | 78 | ``` 79 | $ git branch 80 | ``` 81 | 82 | 会有如下提示(前面的*代表的是当前你所在的工作分支) 83 | 84 | 85 | 86 | 然后切换到你的新分支 87 | 88 | ``` 89 | $ git checkout newbranch 90 | ``` 91 | 92 | 如果不放心,还可以 $ git branch确认下 93 | 94 | 然后将你的改动提交到新分支上 95 | 96 | ``` 97 | $ git add . 98 | $ git commit -m "18.03.01" 99 | ``` 100 | 101 | 然后`git status`检查是否成功 102 | 103 | 104 | 105 | 然后切换到主分支 106 | 107 | ``` 108 | $ git checkout master 109 | ``` 110 | 111 | 然后将新分支提交的改动合并到主分支上 112 | 113 | ``` 114 | $ git merge newbranch 115 | ``` 116 | 117 | 然后就可以push代码了 118 | 119 | ``` 120 | $ git push -u origin master 121 | ``` 122 | 123 | 最后还可以删除这个分支 124 | 125 | ``` 126 | $ git branch -D newbranch 127 | ``` 128 | 129 | 130 | 131 | ---- 132 | 133 | ## 冲突解决 134 | 135 | 如果您舍弃线上的文件,则在推送时选择强制推送,强制推送需要执行下面的命令(默认不推荐该行为): 136 | 137 | ```shell 138 | git push origin master -f 139 | ``` 140 | 141 | 如果您选择保留线上的 readme 文件,则需要先执行: 142 | 143 | ```shell 144 | git pull origin master 145 | ``` 146 | 147 | 148 | 149 | ## **强制覆盖** 150 | 151 | 152 | 153 | ```shell 154 | git fetch --all 155 | git reset --hard origin/master 156 | git pull 157 | ``` 158 | 159 | -------------------------------------------------------------------------------- /Notes/Java/assets/1554616165.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1554616165.png -------------------------------------------------------------------------------- /Notes/Java/assets/1559390873399.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1559390873399.png -------------------------------------------------------------------------------- /Notes/Java/assets/1573029522551.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1573029522551.png -------------------------------------------------------------------------------- /Notes/Java/assets/1573193211462.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1573193211462.png -------------------------------------------------------------------------------- /Notes/Java/assets/1573193226657.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1573193226657.png -------------------------------------------------------------------------------- /Notes/Java/assets/1684165153165.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1684165153165.png -------------------------------------------------------------------------------- /Notes/Java/assets/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/1bea398f-17a7-4f67-a90b-9e2d243eaa9a.png -------------------------------------------------------------------------------- /Notes/Java/assets/2019-05-25_221513.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/2019-05-25_221513.png -------------------------------------------------------------------------------- /Notes/Java/assets/2019-05-25_221529-1560611871423.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/2019-05-25_221529-1560611871423.png -------------------------------------------------------------------------------- /Notes/Java/assets/2019-05-25_221529.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/2019-05-25_221529.png -------------------------------------------------------------------------------- /Notes/Java/assets/2019-05-25_221541.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/2019-05-25_221541.png -------------------------------------------------------------------------------- /Notes/Java/assets/2019-06-01_090652.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/2019-06-01_090652.png -------------------------------------------------------------------------------- /Notes/Java/assets/67bf5487-c45d-49b6-b9c0-a058d8c68902.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/67bf5487-c45d-49b6-b9c0-a058d8c68902.png -------------------------------------------------------------------------------- /Notes/Java/assets/687474703a2f.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/687474703a2f.jpg -------------------------------------------------------------------------------- /Notes/Java/assets/687474707337.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/687474707337.jpg -------------------------------------------------------------------------------- /Notes/Java/assets/80804f52-8815-4096-b506-48eef3eed5c6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/80804f52-8815-4096-b506-48eef3eed5c6.png -------------------------------------------------------------------------------- /Notes/Java/assets/952e06bd-5a65-4cab-82e4-dd1536462f38.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/952e06bd-5a65-4cab-82e4-dd1536462f38.png -------------------------------------------------------------------------------- /Notes/Java/assets/IO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/IO.png -------------------------------------------------------------------------------- /Notes/Java/assets/Java基础.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/Java基础.png -------------------------------------------------------------------------------- /Notes/Java/assets/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/b5bdcbe2-b958-4aef-9151-6ad963cb28b4.png -------------------------------------------------------------------------------- /Notes/Java/assets/clipboard-1573029104100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/clipboard-1573029104100.png -------------------------------------------------------------------------------- /Notes/Java/assets/clipboard-1573034111430.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/clipboard-1573034111430.png -------------------------------------------------------------------------------- /Notes/Java/assets/clipboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/clipboard.png -------------------------------------------------------------------------------- /Notes/Java/assets/dfh484174.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/dfh484174.png -------------------------------------------------------------------------------- /Notes/Java/assets/overview-selectors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/Java/assets/overview-selectors.png -------------------------------------------------------------------------------- /Notes/MongoDB/MongoDB(一)概念.md: -------------------------------------------------------------------------------- 1 | # MongoDB 简介 2 | 3 | MongoDB 是最早热门非关系数据库的之一,使用也比较普遍,一般会用做离线数据分析来使用,放到内网的居。 4 | 5 | MongoDB 基于分布式文件存储的数据库。由C++语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。在高负载的情况下,添加更多的节点,可以保证服务器性能。 6 | 7 | MongoDB 是一个高性能,开源,无模式的文档型数据库,是当前 NoSql 数据库中比较热门的一种。 8 | 9 | MongoDB 最大的特点是他支持的查询语言非常强大,其语法有点类似于面向对象的查询语言,几乎可以实现类似关系数据库单表查询的绝大部分功能,而且还支持对数据建立索引。 10 | 11 | 12 | 13 | **MongoDB 与关系数据库的区别:** 14 | 15 | > 传统的关系数据库一般由数据库(database)、表(table)、记录(record)三个层次概念组成, 16 | > 17 | > MongoDB 是由数据库(database)、集合(collection)、文档对象(document)三个层次组成。 18 | > 19 | > MongoDB 对于关系型数据库里的表,但是集合中没有列、行和关系概念,这体现了模式自由的特点。 20 | > 21 | > MongoDB 中的一条记录就是一个文档,是一个数据结构,由字段和值对组成。MongoDB 文档与 JSON 对象类似![img](assets/crud-annotated-document.png) 22 | 23 | 24 | 25 | **MongoDB 特点:** 26 | 27 | > * MongoDB 是一个面向文档存储的数据库,操作起来比较简单和容易。 28 | > * MongoDB记录中设置任何属性的索引 29 | > * Mongo支持丰富的查询表达式。查询指令使用JSON形式的标记,可轻易查询文档中内嵌的对象及数组。 30 | > * MongoDB 的适合对大量或者无固定格式的数据进行存储,比如:日志、缓存等。对事物支持较弱,不适用复杂的多文档(多表)的级联查询。 31 | 32 | 33 | 34 | 35 | 36 | # 资料参考 37 | 38 | * [纯洁的微笑](http://www.ityouknow.com/springboot/2017/05/08/spring-boot-mongodb.html) 39 | * [菜鸟教程](https://www.runoob.com/mongodb/mongodb-intro.html) -------------------------------------------------------------------------------- /Notes/MongoDB/assets/crud-annotated-document.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/MongoDB/assets/crud-annotated-document.png -------------------------------------------------------------------------------- /Notes/RESTful风格.md: -------------------------------------------------------------------------------- 1 | # RESTful风格 2 | 3 | REST全称是REpresentational State Transfer 直接翻译:表现层状态转移,通俗的说法是:URL定位资源, 4 | 5 | RESTful 的核心思想就是,客户端发出的数据操作指令都是"动词 + 宾语"的结构 6 | 7 | * 动词通常就是五种 HTTP 方法,对应 CRUD 操作 8 | 9 | ```java 10 | GET:读取(Read) 11 | POST:新建(Create) 12 | PUT:更新(Update) 13 | PATCH:更新(Update),通常是部分更新 14 | DELETE:删除(Delete) 15 | ``` 16 | 17 | * 宾语就是 API 的 URL,**必须是名词,不能是动词** 18 | 19 | 名词:名词是复数还是单数,没有统一的规定,建议使用复数,如: 20 | 21 | ```java 22 | /articles 23 | ``` 24 | 25 | 动词:一般指get、set、create、insert等,如: 26 | 27 | ```java 28 | /getAllCars 29 | /createNewCar 30 | /deleteAllRedCars 31 | ``` 32 | 33 | 34 | 35 | **扩展:** 36 | 37 | **HTTP 幂等性:** 38 | 39 | 定义:**是指无论调用这个url多少次,都不会有不同的结果的HTTP方法** 40 | 41 | * 幂等性:GET、PUT、DELETE、HEAD 42 | * 非幂等性:POST、PATCH 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | **响应的数据报文格式:** 51 | 52 | 数据格式,应该是 **JSON** 对象,HTTP 请求头和响应头的`Content-Type`属性要设为`application/json`。 53 | 54 | ``` 55 | { 56 | code:0, 57 | msg:’’ 58 | data:{}||[], 59 | } 60 | ``` 61 | 62 | -------------------------------------------------------------------------------- /Notes/database/MySQL/SQL实战.md: -------------------------------------------------------------------------------- 1 | # 一、基本语法 2 | 3 | ```sql 4 | 1、创建数据库 5 | CREATE DATABASE database-name 6 | 7 | 2、删除数据库 8 | drop database dbname 9 | 10 | 3、备份sql server 11 | --- 创建 备份数据的 device 12 | USE master 13 | EXEC sp_addumpdevice 'disk', 'testBack', 'c:\mssql7backup\MyNwind_1.dat' 14 | --- 开始 备份 15 | BACKUP DATABASE pubs TO testBack 16 | 17 | 4、创建新表 18 | create table tabname(col1 type1 [not null] [primary key],col2 type2 [not null],..) 19 | 20 | 根据已有的表创建新表: 21 | A:create table tab_new like tab_old (使用旧表创建新表) 22 | B:create table tab_new as select col1,col2… from tab_old definition only 23 | 24 | 5、删除新表 25 | drop table tabname 26 | 27 | 6、增加一个列 28 | Alter table tabname add column col type 29 | 注:列增加后将不能删除。DB2中列加上后数据类型也不能改变,唯一能改变的是增加varchar类型的长度。 30 | 31 | 7、添加主键: Alter table tabname add primary key(col) 32 | 删除主键: Alter table tabname drop primary key(col) 33 | 34 | 8、创建索引:create [unique] index idxname on tabname(col….) 35 | 删除索引:drop index idxname 36 | 注:索引是不可更改的,想更改必须删除重新建。 37 | 38 | 9、创建视图:create view viewname as select statement 39 | 删除视图:drop view viewname 40 | 41 | 10、几个简单的基本的sql语句 42 | 选择:select * from table1 where 范围 43 | 插入:insert into table1(field1,field2) values(value1,value2) 44 | 删除:delete from table1 where 范围 45 | 更新:update table1 set field1=value1 where 范围 46 | 查找:select * from table1 where field1 like ’%value1%’ ---like的语法很精妙,查资料! 47 | 排序:select * from table1 order by field1,field2 [desc] 48 | 总数:select count as totalcount from table1 49 | 求和:select sum(field1) as sumvalue from table1 50 | 平均:select avg(field1) as avgvalue from table1 51 | 最大:select max(field1) as maxvalue from table1 52 | 最小:select min(field1) as minvalue from table1 53 | ``` 54 | 55 | 56 | 57 | 58 | 59 | # 日历表 60 | 61 | 当我们在做数据报表的时候,经常会去查询近一段时间显示的数据,但是拿到的数据却是某一天没数据的话是查询不出来的,但是我们希望没数据的那天显示为0 62 | 63 | 这时有两种解决办法 64 | 65 | 其一:重写sql语句,使用 SELECT UNION 一个个写出来,还有一种就是创建日历表 66 | 67 | 其二:在返回数据的java代码中重新拼接数据,先获取三十日的日期,把没数据的补0即可 68 | 69 | 70 | 71 | **创建日历表** 72 | 73 | ```sql 74 | # =====================>> 创建日历表 start <<======================== 75 | DROP TABLE IF EXISTS `num`; 76 | CREATE TABLE `num` (i INT); 77 | INSERT INTO `num` (i) VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9) 78 | 79 | # 日期的表 80 | DROP TABLE IF EXISTS `t_calendar`; 81 | CREATE TABLE t_calendar( 82 | report_date DATE 83 | ); 84 | 85 | -- 生成并插入当前年初前后 10 年的日期数据 86 | INSERT INTO t_calendar(report_date) 87 | SELECT ADDDATE( DATE_SUB(DATE_SUB(curdate(),INTERVAL DAYOFYEAR(CURDATE())-1 DAY),INTERVAL 10 YEAR ) ,numlist.id) AS `date` 88 | FROM( 89 | SELECT id FROM ( 90 | SELECT n1.i + n10.i * 10 + n100.i * 100 + n1000.i * 1000 AS id 91 | FROM num n1 CROSS JOIN num AS n10 CROSS JOIN num AS n100 CROSS JOIN num AS n1000 92 | ) t WHERE t.id<(select TimeStampDiff(DAY,DATE_SUB(DATE_SUB(curdate(),INTERVAL DAYOFYEAR(CURDATE())-1 DAY),INTERVAL 10 YEAR ),DATE_SUB(DATE_SUB(curdate(),INTERVAL DAYOFYEAR(CURDATE())-1 DAY),INTERVAL -11 YEAR ))) 93 | ) AS numlist; 94 | 95 | DROP TABLE `num`; 96 | # =====================>> 创建日历表 end <<======================== 97 | ``` 98 | 99 | 100 | 101 | # 常用关键字 102 | 103 | ## 约束条件 104 | 105 | ```sql 106 | PRIMARY KEY --标识该属性为该表的主键,可以唯一的标识对应的元组 107 | FOREIGN KEY --标识该属性为该表的外键,是与之联系某表的主键 108 | NOT NULL --标识该属性不能为空 109 | UNIQUE --标识该属性的值是唯一的 110 | AUTO_INCREMENT --标识该属性的值是自动增加,这是MySQL的SQL语句的特色 111 | DEFAULT --为该属性设置默认值 112 | ``` 113 | 114 | 115 | 116 | 117 | 118 | # 常用时间处理 119 | 120 | ```sql 121 | -- 计算两个日期之间的时间间隔的方法 122 | select TimeStampDiff(DAY,'2019-01-01','2019-02-03') 123 | ``` 124 | 125 | -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/1053629-370c020e1df96a03.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/1053629-370c020e1df96a03.webp -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/1053629-5a796455662a3544.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/1053629-5a796455662a3544.webp -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/1562926867684.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/1562926867684.png -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/1562926888780.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/1562926888780.png -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/a044ad345982b2b75818ea1c30adcbef77099b67.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/a044ad345982b2b75818ea1c30adcbef77099b67.jpg -------------------------------------------------------------------------------- /Notes/database/MySQL/assets/c1dca4018a0b4818a52c5ab26df8fbeb.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/database/MySQL/assets/c1dca4018a0b4818a52c5ab26df8fbeb.jpg -------------------------------------------------------------------------------- /Notes/database/MySQL/常用SQL脚本.sql: -------------------------------------------------------------------------------- 1 | # 查询版本号 2 | select VERSION(); 3 | #查看当前连接数 4 | SHOW PROCESSLIST; 5 | kill -9 11; 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /Notes/maven/Maven 基础.md: -------------------------------------------------------------------------------- 1 | # Maven 2 | 3 | 是优秀的构建工具,能够帮我们自动化构建过程,从清理、编译、测试到生成报告,在到打包和部署。 4 | 5 | 是依赖管理工具和项目信息管理工具,它提供中央仓库,能帮我们自动下载构件。 6 | 7 | # Maven 基础概念 8 | 9 | groupId、artifactId、version 这3个元素定义了一个项目基本坐标。 10 | 11 | * groupId:定义了项目属于哪个组,这个组往往和项目所在的组织或公司存在关联 12 | 13 | * artifactId:定义了当前Maven项目在组中唯一的ID 14 | 15 | * version :定了项目当前的版本 16 | * scope:依赖范围,告诉Maven这个依赖项资源使用的范围: 17 | * compile ,默认,表明是所有任务所需的资源 18 | * test:测试有效。运行所有的测试用例时所需资源 19 | * provided:JDK部分或应用服务器的classpath所需的资源 20 | * runtime:运行时依赖范围,表明是运行时所需资源 21 | * system:系统依赖范围,和provided一致,但需要使用systemPath显式的指定依赖文件路径 22 | * import:导入依赖 23 | * type,定义打包的类型 24 | * optional: 是否为可选依赖 25 | * exclusions:用来排除传递性依赖 26 | 27 | 28 | 29 | 还有以下常用标签: 30 | 31 | - Dependency:依赖 32 | - Plug-in:maven的插件集合 33 | - Repository:仓库,即放置Artifact的地方 34 | 35 | 36 | 37 | # Maven打包常用命令 38 | 39 | > mvn compile:编译命令(只编译主代码,主代码放在src/main/java/目录下)。会在你的项目路径下生成一个target目录,在该目录中包含一个classes文件夹,里面全是生成的class文件及字节码文件 40 | > 41 | > mvn test:运行应用程序中的单元测试 42 | > 43 | > mvn package:依据项目路径下一个target目录生成jar/war文件, 44 | > 45 | > mvn install:该命令包含了package命令功能,并将项目的jar文件添加到库中, 以备依赖此项目时使用 46 | > 47 | > mvn site:生成项目相关信息的网站 48 | > 49 | > mvn clean:删除项目路径下的target文件,但是不会删除本地的maven仓库已经生成的jar文件 50 | 51 | # 仓库 52 | 53 | 仓库分两类:本地仓库和远程仓库;当maven通过坐标查找构件时,优先查看本地仓库,如果没有在查看远程仓库,在没有maven就会报错。 54 | 55 | ![在这里插入图片描述](assets/20190921212905639.png) 56 | 57 | 本地仓库:一般默认在 C:\Users\(电脑名)\ .m2\repository ,可通过setting文件配置 58 | 59 | 中央仓库:默认的远程仓库 60 | 61 | 私服:架设在局域网内的仓库服务 62 | 63 | 64 | 65 | ## 问题 66 | 67 | 如何解决版本冲突? 68 | 69 | 通过添加标签来解决冲突,找到两个jar包,留下高版本的jar包,去掉低版本的jar包。 70 | 71 | ![在这里插入图片描述](assets/20190921212918827.png) 72 | 73 | 74 | 75 | 76 | 77 | # DepencyManagement 78 | 79 | 通常在多模块项目中用来指定**公共依赖的版本号、scope的控制**,让子项目中引用一个依赖而不用显示的列出版本号。Maven会沿着父子层次向上走,直到找到一个拥有dependencyManagement元素的项目,然后它就会使用在这个dependencyManagement元素中指定的版本号。 80 | 81 | 82 | 83 | 84 | 85 | **与Dependencies区别** 86 | 87 | 相对于dependencyManagement,所有生命在dependencies里的依赖都会自动引入 88 | 89 | **dependencies ** 即使在子项目中不写该依赖项,那么子项目仍然会从父项目中继承该依赖项(全部继承) 90 | 91 | **dependencyManagement里只是声明依赖,并不实现引入**,因此子项目需要显示的声明需要用的依赖。如果不在子项目中声明依赖,是不会从父项目中继承下来的;只有在子项目中写了该依赖项,并且没有指定具体版本,才会从父项目中继承该项,并且version和scope都读取自父pom;另外如果子项目中指定了版本号,那么会使用子项目中指定的jar版本。 -------------------------------------------------------------------------------- /Notes/maven/assets/20190921212905639.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/maven/assets/20190921212905639.png -------------------------------------------------------------------------------- /Notes/maven/assets/20190921212918827.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/maven/assets/20190921212918827.png -------------------------------------------------------------------------------- /Notes/spring/Mybatis原理.md: -------------------------------------------------------------------------------- 1 | # Mybatis 实现原理 2 | 3 | 通过debug 我们发现mybatis实现 4 | 5 | 第一步:通过MapperProxy 动态代理实现 6 | 7 | ```java 8 | public class MapperProxy implements InvocationHandler, Serializable { 9 | 10 | // 核心方法 11 | public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 12 | try { 13 | if (Object.class.equals(method.getDeclaringClass())) { 14 | return method.invoke(this, args); 15 | } 16 | 17 | if (this.isDefaultMethod(method)) { 18 | return this.invokeDefaultMethod(proxy, method, args); 19 | } 20 | } catch (Throwable var5) { 21 | throw ExceptionUtil.unwrapThrowable(var5); 22 | } 23 | 24 | MapperMethod mapperMethod = this.cachedMapperMethod(method); 25 | return mapperMethod.execute(this.sqlSession, args); 26 | } 27 | } 28 | ``` 29 | 30 | 知识点回顾: 31 | 32 | 在java的动态代理机制中,有两个重要的类或接口, InvocationHandler(Interface)、Proxy(Class),这一个类和接口是实现我们动态代理所必须用到的 33 | 34 | 每一个动态代理类都必须要实现InvocationHandler这个接口,并且每个代理类的实例都关联到了一个handler,当我们通过代理对象调用一个方法的时候,这个方法的调用就会被转发为由InvocationHandler这个接口的 invoke 方法来进行调用 35 | 36 | ```java 37 | Object invoke(Object proxy, Method method, Object[] args) throws Throwable 38 | 39 | proxy:  指代我们所代理的那个真实对象 40 | method:  指代的是我们所要调用真实对象的某个方法的Method对象 41 | args:  指代的是调用真实对象某个方法时接受的参数 42 | ``` 43 | 44 | -------------------------------------------------------------------------------- /Notes/spring/assets/1563093613555.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/1563093613555.png -------------------------------------------------------------------------------- /Notes/spring/assets/1563093796975.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/1563093796975.png -------------------------------------------------------------------------------- /Notes/spring/assets/1563413836956.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/1563413836956.png -------------------------------------------------------------------------------- /Notes/spring/assets/1563415103412.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/1563415103412.png -------------------------------------------------------------------------------- /Notes/spring/assets/1563415298386.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/1563415298386.png -------------------------------------------------------------------------------- /Notes/spring/assets/2019-06-08_113939.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/2019-06-08_113939.png -------------------------------------------------------------------------------- /Notes/spring/assets/Realm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/Realm.png -------------------------------------------------------------------------------- /Notes/spring/assets/SessionDAO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/SessionDAO.png -------------------------------------------------------------------------------- /Notes/spring/assets/SessionManager-1560484324202.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/SessionManager-1560484324202.png -------------------------------------------------------------------------------- /Notes/spring/assets/SessionManager.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/SessionManager.png -------------------------------------------------------------------------------- /Notes/spring/assets/ShiroArchitecture.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/ShiroArchitecture.png -------------------------------------------------------------------------------- /Notes/spring/assets/ShiroAuthenticationSequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/ShiroAuthenticationSequence.png -------------------------------------------------------------------------------- /Notes/spring/assets/ShiroAuthorizationSequence.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/ShiroAuthorizationSequence.png -------------------------------------------------------------------------------- /Notes/spring/assets/ShiroFeatures.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/ShiroFeatures.png -------------------------------------------------------------------------------- /Notes/spring/assets/aop-proxy-call.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/aop-proxy-call.png -------------------------------------------------------------------------------- /Notes/spring/assets/e8f97e5a29a54882a3189bc5a21e8015.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/e8f97e5a29a54882a3189bc5a21e8015.jpg -------------------------------------------------------------------------------- /Notes/spring/assets/mvc-context-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/spring/assets/mvc-context-hierarchy.png -------------------------------------------------------------------------------- /Notes/springboot/assets/1569492250582.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/springboot/assets/1569492250582.png -------------------------------------------------------------------------------- /Notes/springboot/assets/1569492566123.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/springboot/assets/1569492566123.png -------------------------------------------------------------------------------- /Notes/springboot/assets/9770936-3d0012126b210ec2.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Notes/springboot/assets/9770936-3d0012126b210ec2.webp -------------------------------------------------------------------------------- /Notes/springboot/springboot 动态定时任务持久化.md: -------------------------------------------------------------------------------- 1 | # SpringBoot 动态定时任务持久化 2 | 3 | # Quartz依赖 4 | 5 | ```xml 6 | 7 | 8 | org.springframework.boot 9 | spring-boot-starter-quartz 10 | 11 | 12 | ``` 13 | 14 | 15 | 16 | # sql脚本 17 | 18 | 很多人的博文中都没有SQL脚本,很多朋友都不知道怎么获取SQL脚本,这里解密一下,该SQL脚本是由官方定义好的,可以直接去官网下载的。但是下载注意了,版本的不同可能有稍微变化。 19 | 20 | 我们根据spring-boot-starter-quartz 依赖找到对应的版本,如下: 21 | 22 | ![1569492250582](assets/1569492250582.png) 23 | 24 | 25 | 26 | 然后到官网下载相应的tar.gz包,[官方地址](http://www.quartz-scheduler.org/downloads/),解压后在src\org\quartz\impl\jdbcjobstore下,找到相应的数据库脚本, 27 | 28 | ![1569492566123](assets/1569492566123.png) 29 | 30 | -------------------------------------------------------------------------------- /Notes/springboot/springboot(一) 简介.md: -------------------------------------------------------------------------------- 1 | # Spring Boot 介绍 2 | 3 | 4 | 5 | # springboot特点 6 | 7 | springboot 有三单特点:**自动配置、起步依赖、Actuator对运行状态的监控** 8 | 9 | 10 | 11 | 自动配置和起步依赖解决了Spring的xml配置和依赖管理依赖的各种问题(如:依赖冲突) 12 | 13 | > 优点: 14 | > 15 | > Spring Boot 不仅提供了自动装配、起步依赖,还自带多种功能,如:安全、度量、健康检查、内嵌Servlet容器、外置配置。 16 | > 17 | > 开发人员可以更加敏捷、且更加专注程序本身的业务开发 18 | > 19 | > 另外,Actuator提供了运行时的Spring Boot程序中的监控端点,让开发人员和运维人员实时了解程序的运行状况 -------------------------------------------------------------------------------- /Notes/springboot/springboot(二) 配置文件.md: -------------------------------------------------------------------------------- 1 | # springboot(二) 配置文件 2 | 3 | # @Value读取配置文件 4 | 5 | 我们最常见读取配置文件内的信息时,通常使用@Value ,如下: 6 | 7 | application.properties: 8 | 9 | ```properties 10 | my.name=husy 11 | ``` 12 | 13 | java 代码 14 | 15 | ```java 16 | @RunWith(SpringRunner.class) 17 | @SpringBootTest 18 | public class HusyDemoApplicationTests { 19 | @Value("${my.name}") 20 | private String name; 21 | @Test 22 | public void contextLoads() { 23 | System.out.println(name); 24 | } 25 | } 26 | ``` 27 | 28 | 该方式有个不好的地方,就是在使用时,需要注意@Value注解是否生效的问题。一般使用有以下注意事项 29 | 30 | * 不能作用于静态变量(static) 31 | * 不能作用于常量(final) 32 | * 不能在非注册的类中使用(类需要被注册在spring上下文中,如用@Service,@RestController,@Component等) 33 | * 使用这个类时,只能通过依赖注入的方式,用new的方式是不会自动注入这些配置的 34 | 35 | 36 | 37 | 为什么呢? 我们可以通过Spring在初始化Bean的过程了解 38 | 39 | ![img](assets/9770936-3d0012126b210ec2.webp) 40 | 41 | 解释一下: 42 | 43 | 1. 读取定义 44 | 2. Bean Factory Post Processing 45 | 3. 实例化 46 | 4. 属性注入 47 | 5. Bean Post Processing 48 | 49 | 这个问题的原因就很明显了。@Value注入是在第四步,而初始化变量是在第三部,这个使用变量还没有被注入,自然为null了。 50 | 51 | 52 | 53 | # Environment读取配置文件 54 | 55 | Environment会加载application.properties和application-$(profile).properties文件 56 | 57 | ```java 58 | @RunWith(SpringRunner.class) 59 | @SpringBootTest 60 | public class HusyDemoApplicationTests { 61 | @Autowired 62 | private Environment environment; 63 | 64 | @Test 65 | public void contextLoads() { 66 | System.out.println("name:"+environment.getProperty("my.name") 67 | +",age:"+environment.getProperty("my.age")); 68 | } 69 | } 70 | ``` 71 | 72 | 73 | 74 | # 将配置文件装配到实体类 75 | 76 | 当有读取很多配置属性时,如果逐个读取属性会非常麻烦,通常会把这些属性作为一个变量名来创建一个JavaBean 的变量 77 | 78 | 如在application.yml 中属性如下: 79 | 80 | > my: 81 | > 82 | > ​ name: husy 83 | > 84 | > ​ age: ${random.int} 85 | 86 | 如何赋值给JavaBean 对象,代码如下: 87 | 88 | ```java 89 | @Data 90 | @Component 91 | @ConfigurationProperties(prefix = "my") 92 | public class ConfigBean { 93 | private String name; 94 | private int age; 95 | } 96 | ``` 97 | 98 | @ConfigurationProperties 表明该类为配置属性类,并配置前缀为prefix对应的属性 99 | 100 | @Component 将bean注入容器,如果没有,可在启动类上加上@EnableConfigurationProperties注解 101 | 102 | 如下: 103 | 104 | ```java 105 | @RunWith(SpringRunner.class) 106 | @SpringBootTest 107 | @EnableConfigurationProperties({ConfigBean.class}) 108 | public class HusyDemoApplicationTests { 109 | @Autowired 110 | ConfigBean configBean; 111 | @Test 112 | public void contextLoads() { 113 | System.out.println(configBean.toString()); 114 | } 115 | } 116 | ``` 117 | 118 | 119 | 120 | # 多个配置文件读取 121 | 122 | 当我们有多个配置文件时,通过@PropertySource指定读取的配置文件,如下: 123 | 124 | ```java 125 | @Data 126 | @Component 127 | @PropertySource(value = "classpath:test.properties") 128 | @ConfigurationProperties(prefix = "my") 129 | public class ConfigBean { 130 | private String name; 131 | private int age; 132 | } 133 | ``` 134 | 135 | 136 | 137 | # 多环境的配置文件 138 | 139 | 在实际开发过程中,可能有多个不同的环境配置文件,Spring Boot 支持启动时在配置文件application.yml中指定环境的配置环境,配置文件格式为application-{profile}.properties,其中{profile}对应环境标识,例如: 140 | 141 | >application-test.properties 测试环境 142 | > 143 | >application-dev.properties 开发环境 144 | > 145 | >application-prod.properties 生产环境 146 | 147 | 如何指定使用哪个环境配置文件,只需要在application.yml 中配置上spring.Profiles.active,该配置标识系统将采用哪个profiles。 148 | 149 | 150 | 151 | 当然我们也可以通过 java -jar 这种方式启动程序,并指定程序的配置文件,启动命令如下: 152 | 153 | > java -jar springbootdemo.jar --spring.profiles.acitve=dev -------------------------------------------------------------------------------- /Notes/面试谈话技巧.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 向面试官提问 4 | 5 | 一般面试时,无论技术面试官还是人事面试官都会问我们, 6 | 普通的面试者,一般只知道问公司的福利待遇、是否加班、有没有加班补助等问题。这些问题无法体现你对公司的关注面,也无法了解这个公司情况,下面列举一下常见的问题。帮助你做到充分了解公司情况 7 | 8 | 9 | **向技术面试官提问** 10 | * 我入职后,加入什么项目组,该项目组是做什么的,主要使用那些技术 11 | * 公司一般使用的技术栈有哪些? 12 | * 公司主打产品有哪些,分别使用什么技术? 13 | * 公司的项目组一般有多少技术人员。 14 | * 公司的加班情况怎么样,加班有什么补偿? 15 | * 公司或项目组接下来一年的发展计划 16 | * 公司有没有技术大牛 17 | * 公司的工作环境能不能上网 18 | 19 | **向HR 提问** 20 | * 公司的有没有加薪,涨幅多少,最少加多少,一年几次 21 | * 公司有没有年假,一般多少天 22 | * 公司有没有年终奖,年前发还是年后发 23 | * 公司是否是弹性打卡 24 | * 公司实习期多长,实习期薪资,实习期考核标准 25 | * 如果面试通过,什么时候发放offer 26 | 27 | 28 | 29 | # 谈论离职原因 30 | 31 | 面试时一般面试官也会问这个“为什么从上家公司辞职?” 32 | 33 | * 避免谈公司和领导的不好 34 | * 从自身主观和客观原因谈 35 | 36 | 37 | **主观上:** 38 | * 想找更大的发展平台 39 | * 上家公司晋升空间狭窄 40 | * 之前行业不适合自己长期发展 41 | 42 | 43 | **客观上:** 44 | * 搬家后离公司太远 45 | * 家里需要照顾想找离家近的公司 46 | * 公司倒闭了 47 | 48 | 49 | 50 | **错误回答:** 51 | 52 | 1、因为工作加班多,比较累。 53 | 54 | 2、同事太勾心斗角工作不愉快。 55 | 56 | 3、离家太远。 57 | 58 | 4、工作太久了,想换个工作环境。 59 | 60 | 61 | 62 | # 谈薪技巧 63 | 64 | 谈薪前可以先咨询公司的福利情况,主要是年终奖发放情况,然后根据自己能力水平,给出一个薪资范围,最好不要是具体数额 -------------------------------------------------------------------------------- /Project/README.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Project/README.md -------------------------------------------------------------------------------- /Question/JavaQuestion.md: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Question/JavaQuestion.md -------------------------------------------------------------------------------- /RPC/分布式微服务(1)微服务架构/1569727322900.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/RPC/分布式微服务(1)微服务架构/1569727322900.png -------------------------------------------------------------------------------- /RPC/分布式微服务(1)微服务架构/1569729288376.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/RPC/分布式微服务(1)微服务架构/1569729288376.png -------------------------------------------------------------------------------- /RPC/分布式微服务(1)微服务架构/1569743798115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/RPC/分布式微服务(1)微服务架构/1569743798115.png -------------------------------------------------------------------------------- /RPC/分布式微服务(1)微服务架构/1569744276427.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/RPC/分布式微服务(1)微服务架构/1569744276427.png -------------------------------------------------------------------------------- /Sys/Linux常用命令(1)文件管理命令.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 文件管理 4 | 5 | 常用:ls、cp、mkdir、touch、mv、rm、rename、find、which 6 | 7 | 8 | 9 | ## ls命令 10 | 11 | ls 命令是Linux下最常用的指令之一。ls命令为英文单词 list 的缩写;其功能是列出指定目录下的内容及其相关属性信息。 12 | 13 | > 语法格式: ls [选项] [文件] 14 | > 15 | > 常用参数: 16 | > 17 | > -a :显示所有文件及目录 (包括以“.”开头的隐藏文件) 18 | > 19 | > -l :使用长格式列出文件及目录信息 20 | > 21 | > -r :将文件以相反次序显示(默认依英文字母次序) 22 | > 23 | > -t :根据最后的修改时间排序 24 | > 25 | > -A :同 -a ,但不列出 “.” (当前目录) 及 “..” (父目录) 26 | > 27 | > -S :根据文件大小排序 28 | > 29 | > -R :递归列出所有子目录 30 | 31 | 常用实例 32 | 33 | ```shell 34 | #列出所有文件(包括隐藏文件) 35 | ls -a 36 | #列出文件的详细信息 37 | ls -l 38 | #列出当前工作目录下所有名称是 “s” 开头的文件 39 | ls s* 40 | ``` 41 | 42 | 43 | 44 | ## cp命令 45 | 46 | 将复制一个或多个文件到一个具体的文件名或一个已经存在的目录下 47 | 48 | > **语法格式:**cp [参数] [文件] 49 | > 50 | > **常用参数:** 51 | > 52 | > -f:若目标文件已存在,则会直接覆盖原文件 53 | > 54 | > -i:若目标文件已存在,则会询问是否覆盖 55 | > 56 | > -p:保留源文件或目录的所有属性 57 | > 58 | > -r:递归方式目录及其下的文件 59 | > 60 | > -d:当复制符号连接时,把目标文件或目录也建立为符号连接,并指向与源文件或目录连接的原始文件或目录 61 | > 62 | > -l:对源文件建立硬连接,而非复制文件 63 | > 64 | > -s:对源文件建立符号连接,而非复制文件 65 | > 66 | > -b:覆盖已存在的文件目标前将目标文件备份 67 | > 68 | > -v:详细显示cp命令执行的操作过程 69 | > 70 | > -a:等价于“dpr”选项 71 | 72 | 常用实例 73 | 74 | ```shell 75 | # 递归方式目录及其下的文件 76 | cp -r dir1 dir2 77 | # 复制多个文 78 | cp -r file1 file2 file3 dir 79 | # 将文件test1改名为test2 80 | cp -f test1 test2 81 | ``` 82 | 83 | 84 | 85 | ## mkdir命令 86 | 87 | mkdir命令是“make directories”的缩写,用来创建目录; 88 | 89 | 注意:默认状态下,如果要创建的目录已经存在,则提示已存在,而不会继续创建目录 90 | 91 | > 语法格式 : mkdir [参数] [目录] 92 | > 93 | > -p:递归创建多级目录 94 | > 95 | > -m:建立目录的同时设置目录的权限 96 | > 97 | > -z:设置安全上下文 98 | > 99 | > -v:显示目录的创建过程 100 | 101 | 常用实例 102 | 103 | ```shell 104 | #建立一个名为 dir 的子目录 105 | mkdir dir 106 | #递归创建多级子目录 107 | mkdir -p dir/dir2/dir2 108 | ``` 109 | 110 | **touch命令** 111 | 112 | touch命令有两个功能:一是创建新的空文件,二是改变已有文件的时间戳属性 113 | 114 | > 语法格式:touch [参数] [文件] 115 | > 116 | > 常用参数: 117 | > 118 | > a 改变档案的读取时间记录。 119 | > 120 | > m 改变档案的修改时间记录。 121 | > 122 | > c 假如目的档案不存在,不会建立新的档案。与 --no-create 的效果一样。 123 | > 124 | > f 不使用,是为了与其他 unix 系统的相容性而保留。 125 | > 126 | > r 使用参考档的时间记录,与 --file 的效果一样。 127 | > 128 | > d 设定时间与日期,可以使用各种不同的格式。 129 | > 130 | > t 设定档案的时间记录,格式与 date 指令相同。 131 | > 132 | > --no-create 不会建立新档案。 133 | > 134 | > --help 列出指令格式。 135 | > 136 | > --version 列出版本讯息。 137 | 138 | 常用实例 139 | 140 | ```shell 141 | #创建空文件file.txt 142 | touch file.txt 143 | # 批量创建文件file1.txt file2.txt file3.txt file4.txt file5.txt 144 | touch file{1..5}.txt 145 | #如果file.txt不存在,则不创建文件 146 | ``` 147 | 148 | 149 | 150 | ## mv命令 151 | 152 | mv 命令用来为文件或目录改名、或将文件或目录移入其它位置。 153 | 154 | > 语法格式: 155 | > 156 | > mv [options] source dest mv [options] source... directory 157 | > 158 | > 参数说明: 159 | > 160 | > -i: 若指定目录已有同名文件,则先询问是否覆盖旧文件; 161 | > 162 | > -f: 在 mv 操作要覆盖某已有的目标文件时不给任何指示; 163 | 164 | 常用实例 165 | 166 | ```shell 167 | # 将文件 aaa 更名为 bbb 168 | mv aaa bbb 169 | # 将文件file移动到目录dir中 170 | mv file /dir 171 | # 将目录dir1下的文件移动到当前目录下 172 | mv /dir1/* . 173 | ``` 174 | 175 | 176 | 177 | ## rm命令 178 | 179 | rm命令用于删除一个文件或者目录 180 | 181 | > 语法格式:rm [options] name... 182 | > 183 | > 常用参数: 184 | > 185 | > -i 删除前逐一询问确认。 186 | > 187 | > -f 即使原档案属性设为唯读,亦直接删除,无需逐一确认。 188 | > 189 | > -r 将目录及以下之档案亦逐一删除。 190 | > 191 | > 192 | 193 | 常用实例: 194 | 195 | ```shell 196 | # 删除文件,需要确认 197 | rm file.txt 198 | # 删除目录及以下之档案 199 | rm -r file 200 | # 直接删除目录及以下之档案,无需确认 201 | rm -rf file 202 | ``` 203 | 204 | 205 | 206 | ## rename命令 207 | 208 | 用字符串替换的方式批量改变文件名 209 | 210 | > 语法格式:rename [参数] 211 | > 212 | > 常用参数: 213 | > 214 | > ?:可替代单个字符 215 | > 216 | > *:可替代多个字符 217 | 218 | 常用实例 219 | 220 | ```shell 221 | #将test1.txt重命名为test2.txt 222 | rename test1.txt test2.txt 223 | 224 | 将所有以jpg结尾的文件重命名为以png结尾的文件 225 | rename .jpg .png *.jpg 226 | 227 | #文件夹中有这些文件:foo1, …, foo9, foo10, …, foo163,把foo1到foo9的文件重命名为foo01到foo09: 228 | rename foo foo0 foo? 229 | #把foo01到foo99的所有文件重命名为foo001到foo099: 230 | rename foo foo0 foo?? 231 | #把foo001到foo163的所有文件重命名为foo0001到foo0163: 232 | rename foo foo0 foo* 233 | 把foo0100到foo0163的所有文件重命名为foo100到foo163: 234 | rename foo0 foo foo0[1]* 235 | ``` 236 | 237 | 238 | 239 | ## find命令 240 | 241 | find命令用来在指定目录下查找文件;如果使用该命令时,不设置任何参数,则find命令将在当前目录下查找子目录与文件。并且将查找到的子目录和文件全部进行显示。 242 | 243 | > 语法格式:find [路径] [参数] [查找和搜索范围] 244 | > 245 | > 常用参数: 246 | > 247 | > -name:按名称查找 248 | > 249 | > -size:按大小查找 250 | > 251 | > -user:按属性查找 252 | > 253 | > -type:按类型查找 254 | > 255 | > -iname:忽略大小写查找 256 | 257 | 常用实例: 258 | 259 | ```shell 260 | #使用-name参数查看/etc目录下面所有的.conf结尾的配置文件: 261 | find /etc -name "*.conf 262 | #使用-size参数查看/etc目录下面大于1M的文件 263 | find /etc -size +1M 264 | ``` 265 | 266 | 267 | 268 | ## which命令 269 | 270 | 用于查找文件,在PATH变量指定的路径中,搜索某个系统命令的位置 271 | 272 | > 语法格式:which [文件...] 273 | > 274 | > 常用参数 275 | > 276 | > -n<文件名长度>  指定文件名长度,指定的长度必须大于或等于所有文件中最长的文件名。 277 | > 278 | > -p<文件名长度>  与-n参数相同,但此处的<文件名长度>包括了文件的路径。 279 | > 280 | > -w  指定输出时栏位的宽度。 281 | > 282 | > -V  显示版本信息。 283 | 284 | 常用实例: 285 | 286 | ```shell 287 | #查找文件、显示命令路径: 288 | which java 289 | ``` 290 | 291 | 292 | 293 | # 参考资料 294 | 295 | * [Linux命令大全(手册)](https://www.linuxcool.com) 296 | * [Linux 命令大全 | 菜鸟教程](https://www.runoob.com/linux/linux-comm-touch.html) 297 | -------------------------------------------------------------------------------- /Sys/Linux常用命令(2)文档操作.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # 文档操作 6 | 7 | 常用:cat、less、more、tail、vi/vim 8 | 9 | ## cat命令 10 | 11 | 查看文件内容的命令 12 | 13 | > 语法格式:cat [参数] [文件] 14 | > 15 | > 常用参数: 16 | > 17 | > -n 或 --number:由 1 开始对所有输出的行数编号。 18 | > 19 | > -b 或 --number-nonblank:和 -n 相似,只不过对于空白行不编号。 20 | > 21 | > -s 或 --squeeze-blank:当遇到有连续两行以上的空白行,就代换为一行的空白行。 22 | > 23 | > -v 或 --show-nonprinting:使用 ^ 和 M- 符号,除了 LFD 和 TAB 之外。 24 | > 25 | > -E 或 --show-ends : 在每行结束处显示 $。 26 | > 27 | > -T 或 --show-tabs: 将 TAB 字符显示为 ^I。 28 | > 29 | > -A, --show-all:等价于 -vET。 30 | > 31 | > -e:等价于"-vE"选项; 32 | > 33 | > -t:等价于"-vT"选项; 34 | 35 | 常用实例 36 | 37 | ```shell 38 | 查看文件的内容 39 | cat filename.txt 40 | 查看文件的内容,并显示行数编号 41 | cat -n filename.txt 42 | 查看文件的内容,并添加行数编号后输出到另外一个文件中 43 | cat -n linuxcool.log > linuxprobe.log 44 | 清空 /etc/test.txt 文档内容: 45 | cat /dev/null > /etc/test.txt 46 | ``` 47 | 48 | 命令内部操作: 49 | 50 | * Ctrl+S键,停止滚屏; 51 | * Ctrl+Q键可以恢复滚屏; 52 | * Ctrl+C(中断)键则可以终止该命令的执行。 53 | 54 | 55 | 56 | 57 | 58 | ## less命令 59 | 60 | 浏览文字档案的内容,使用 less 可以随意浏览文件,而 more 仅能向前移动,却不能向后移动,而且 less 在查看之前不会加载整个文件 61 | 62 | > 语法格式:less [参数] [文件] 63 | > 64 | > 常用参数: 65 | > 66 | > -b <缓冲区大小> 设置缓冲区的大小 67 | > 68 | > -e 当文件显示结束后,自动离开 69 | > 70 | > -f 强迫打开特殊文件,例如外围设备代号、目录和二进制文件 71 | > 72 | > -g 只标志最后搜索的关键词 73 | > 74 | > -i 忽略搜索时的大小写 75 | > 76 | > -m 显示类似more命令的百分比 77 | > 78 | > -N 显示每行的行号 79 | > 80 | > -o <文件名> 将less 输出的内容在指定文件中保存起来 81 | > 82 | > -Q 不使用警告音 83 | > 84 | > -s 显示连续空行为一行 85 | > 86 | > -S 行过长时间将超出部分舍弃 87 | > 88 | > -x <数字> 将"tab"键显示为规定的数字空格 89 | 90 | 常用实例: 91 | 92 | ```shell 93 | #查看文件 94 | less log2013.log 95 | ``` 96 | 97 | 命令内部操作: 98 | 99 | * / 字符串:向下搜索"字符串"的功能 100 | * ? 字符串:向上搜索"字符串"的功能 101 | * n:重复前一个搜索(与 / 或 ? 有关) 102 | * N:反向重复前一个搜索(与 / 或 ? 有关) 103 | 104 | * b: 向后翻一页 105 | * d: 向后翻半页 106 | * h: 显示帮助界面 107 | * Q: 退出less 命令 108 | * u: 向前滚动半页 109 | * y: 向前滚动一行 110 | * 空格键: 滚动一页 111 | * 回车键: 滚动一行 112 | 113 | 114 | 115 | ## more命令 116 | 117 | more 命令类似 cat ,不过会以一页一页的形式显示,更方便使用者逐页阅读,而最基本的指令就是按空白键(space)就往下一页显示,按 b 键就会往回(back)一页显示,而且还有搜寻字串的功能(与 vi 相似),使用中的说明文件,请按 h; 118 | 119 | > 语法格式:more [参数] [文件] 120 | > 121 | > 常用参数: 122 | > 123 | > -num 一次显示的行数 124 | > 125 | > -d 提示使用者,在画面下方显示 [Press space to continue, 'q' to quit.] ,如果使用者按错键,则会显示 [Press 'h' for instructions.] 而不是 '哔' 声 126 | > 127 | > -l 取消遇见特殊字元 ^L(送纸字元)时会暂停的功能 128 | > 129 | > -f 计算行数时,以实际上的行数,而非自动换行过后的行数(有些单行字数太长的会被扩展为两行或两行以上) 130 | > 131 | > -p 不以卷动的方式显示每一页,而是先清除萤幕后再显示内容 132 | > 133 | > -c 跟 -p 相似,不同的是先显示内容再清除其他旧资料 134 | > 135 | > -s 当遇到有连续两行以上的空白行,就代换为一行的空白行 136 | > 137 | > -u 不显示下引号 (根据环境变数 TERM 指定的 terminal 而有所不同) 138 | > 139 | > +/pattern 在每个文档显示前搜寻该字串(pattern),然后从该字串之后开始显示 140 | > 141 | > +num 从第 num 行开始显示 142 | > 143 | > fileNames 欲显示内容的文档,可为复数个数 144 | 145 | 常用参数: 146 | 147 | ```shell 148 | 显示文件file的内容,显示之前先清屏,附已显示的百分比 149 | more -dc file 150 | 显示文件file的内容,每10行显示一次,而且在显示之前先清屏: 151 | more -c -10 file 152 | 从第 20 行开始显示 file 之文档内容 : 153 | more +20 file 154 | ``` 155 | 156 | 命令内部操作: 157 | 158 | * Space键:显示文本的下一屏内容 159 | * Enter键:向下n行,需要定义,默认为1行 160 | * 斜线符\:接着输入一个模式,可以在文本中寻找下一个相匹配的模式 161 | * H键:显示帮助屏 162 | * B键:显示上一屏内容 163 | * Q键:退出more命令 164 | * Ctrl+F、空格键:向下滚动一屏 165 | * Ctrl+B:返回上一屏 166 | * =: 输出当前的行号 167 | * :f:输出文件名和当前的行号 168 | * V:调用vi编辑器 169 | * !:调用Shell,并执行命令 170 | 171 | 172 | 173 | ## tail命令 174 | 175 | tail用于显示文件尾部的内容,默认在屏幕上显示指定文件的末尾10行 176 | 177 | > 语法格式:tail [参数] [文件] 178 | > 179 | > 常用参数: 180 | > 181 | > -f 循环读取 182 | > 183 | > -q 不显示处理信息 184 | > 185 | > -v 显示详细的处理信息 186 | > 187 | > -c<数目> 显示的字节数 188 | > 189 | > -n<行数> 显示文件的尾部 n 行内容 190 | > 191 | > --pid=PID 与-f合用,表示在进程ID,PID死掉之后结束 192 | > 193 | > -q, --quiet, --silent 从不输出给出文件名的首部 194 | > 195 | > -s, --sleep-interval=S 与-f合用,表示在每次反复的间隔休眠S秒 196 | 197 | 常用实例 198 | 199 | ```shells 200 | #显示文件file的最后10行 201 | tail file 202 | 显示文件file的内容,从第20行至文件末尾 203 | tail +20 file 204 | 显示文件file的最后10个字符 205 | tail -c 10 file 206 | 一直变化的文件总是显示后10行 207 | tail -f 10 file 208 | ``` 209 | 210 | 211 | 212 | ## vi/vim 213 | 214 | 基本上 vi/vim 共分为三种模式,分别是**命令模式**,**输入模式**和**底线命令模式** 215 | 216 | * 命令模式:用户刚刚启动 vi/vim,便进入了命令模式。 217 | * 输入模式:在命令模式下按下 i (或者Insert键)就进入了输入模式。 218 | * 底线命令模式:在命令模式下按下 :(英文冒号)就进入了底线命令模式。 219 | 220 | 命令模式: 221 | 222 | /word: 在文件中查找内容为word的字符串(向下查找) 223 | 224 | ?word: 在文件中查找内容为word的字符串(向上查找) 225 | 226 | 输入模式下操作: 227 | 228 | * **字符按键以及Shift组合**,输入字符 229 | * **ENTER**,回车键,换行 230 | * **BACK SPACE**,退格键,删除光标前一个字符 231 | * **DEL**,删除键,删除光标后一个字符 232 | * **方向键**,在文本中移动光标 233 | * **HOME**/**END**,移动光标到行首/行尾 234 | * **Page Up**/**Page Down**,上/下翻页 235 | * **Insert**,切换光标为输入/替换模式,光标将变成竖线/下划线 236 | * **ESC**,退出输入模式,切换到命令模式 237 | 238 | 底线命令模式操作: 239 | 240 | * :q 退出程序 241 | * :w 保存文件 242 | * :q! 强制退出 243 | * :w! 强制保存文件 -------------------------------------------------------------------------------- /Web/Spring(1)介绍.md: -------------------------------------------------------------------------------- 1 | # **Spring** 介绍 2 | 3 | 它是一个全面的、企业应用开发一站式的解决方案,贯穿表现层、业务层、持久层。但是 Spring仍然可以和其他的框架无缝整合。 4 | 5 | ![](Spring(1)介绍/2019-06-08_113939.png) 6 | 7 | **Spring 的优势** 8 | 9 | * 低侵入 / 低耦合 (降低组件之间的耦合度,实现软件各层之间的解耦) 10 | * 支持声明式事务管理(基于切面和惯例) 11 | * 方便集成其他框架(如MyBatis、Hibernate) 12 | * 降低 Java 开发难度 13 | 14 | 15 | 16 | # Bean 生命周期 17 | 18 | > 1. 容器寻找Bean的定义信息并将其实例化 19 | > 2. 使用依赖注入,spring按照Bean定义信息配置Bean的所有属性 20 | > 3. 如果Bean实现了BeanNameAware接口,工厂调用Bean的SetBeanName()方法传递Bean的ID 21 | > 4. 如果Bean实现了BeanFactoryAware接口,工厂调用setBeanFactory()方法传入工厂自身 22 | > 5. 如果BeanPostProcessor和Bean关联,那么其postProcessBeforeInitialization()方法将被调用 23 | > 6. 如果Bean指定了init-method方法,将被调用 24 | > 7. 最后,如果有BeanPostProcessor和Bean关联,那么其postProcessAfterInitialization()方法将被调用 25 | 26 | 27 | 28 | 此时,Bean已经可以被应用系统使用,并将被保留在BeanFactory中知道他不再被需要。有两种可以将其从BeanFactory中删除掉的方法 29 | 30 | ① 如果Bean实现了DisposableBean接口,destroy()方法将被调用 31 | 32 | ② 如指定了定制的销毁方法,就调用这个方法 -------------------------------------------------------------------------------- /Web/Spring(1)介绍/2019-06-08_113939.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Web/Spring(1)介绍/2019-06-08_113939.png -------------------------------------------------------------------------------- /Web/Spring(2)IOC和DI.md: -------------------------------------------------------------------------------- 1 | # IOC 2 | 3 | 即“**控制反转**”,指将对象的创建交给外部容器控制。之前自己手动的创建对象,现在变成由Spring容器帮助创建生成新的对象 4 | 5 | 分析一下: 6 | 7 |   ●谁控制谁,控制什么:当然是IoC 容器控制了对象;控制什么?那就是主要控制了外部资源获取(不只是对象包括比如文件等)。 8 | 9 |   ●为何是反转,哪些方面反转了:原来是主动获取对象,现在通过容器帮我们查找及注入依赖对象,对象只是被动的接受依赖对象,所以依赖对象的获取被反转了。 10 | 11 | 12 | 13 | ```java 14 | Peron p1 = new Person(); ----->自己手动完成 15 | Person p2 = spring容器.get***(); ----->由spring容器创建 16 | ``` 17 | 18 | 19 | 20 | # DI 21 | 22 | 即“**依赖注入**”,由容器动态的将某个依赖关系注入到组件之中。目的是为了提升组件重用的频率,并为系统搭建一个灵活、可扩展的平台。 23 | 24 | 25 | 26 | 分析一下: 27 | 28 |   ●谁依赖于谁:应用程序依赖于IoC容器; 29 | 30 |   ●为什么需要依赖:应用程序需要IoC容器来提供对象需要的外部资源; 31 | 32 |   ●谁注入谁:IoC容器注入应用程序某个对象,应用程序依赖的对象; 33 | 34 |   ●注入了什么:注入某个对象所需要的外部资源(包括对象、资源、常量数据)。 35 | 36 | 37 | 38 | 依赖注入一般注入可以是基本类型、字符串、对象的引用、集合(List,Set,Map) 39 | 40 | 41 | 42 | # Bean的获取方式 43 | 44 | 1. 通过读取XML文件反射生成对象 45 | 2. 通过Spring提供的utils类获取ApplicationContext对象 46 | 3. 继承自抽象类ApplicationObjectSupport 47 | 4. 继承自抽象类WebApplicationObjectSupport 48 | 5. 实现接口ApplicationContextAware(推荐) 49 | 50 | 51 | 52 | **通过读取XML文件** 53 | 54 | ```xml 55 | 56 | ``` 57 | 58 | ```java 59 | ApplicationContext context= new FileSystemXmlApplicationContext("applicationContext.xml"); 60 | context.getBean("userService"); 61 | ``` 62 | 63 | 64 | 65 | **通过Spring提供的utils类获取ApplicationContext对象** 66 | 67 | ```java 68 | ApplicationContext context1= WebApplicationContextUtils.getRequiredWebApplicationContext(ServletContext sc); 69 | ApplicationContext context2= WebApplicationContextUtils.getWebApplicationContext(ServletContext sc); 70 | context1.getBean("beanId"); 71 | context2.getBean("beanId"); 72 | ``` 73 | 74 | 这样的方式适合于Spring框架的B/S系统,通过ServletContext对象获取ApplicationContext对象。 75 | 76 | 上面两个工具方式的差别是,前者在获取失败时抛出异常。后者返回null。 77 | 78 | 79 | 80 | 81 | 82 | **继承自抽象类ApplicationObjectSupport** 83 | 84 | 抽象类ApplicationObjectSupport提供getApplicationContext()方法 85 | 86 | ```java 87 | @Component 88 | public class SpringBeanUtil extends ApplicationObjectSupport { 89 | //提供一个接口,获取容器中的Bean实例,根据名称获取 90 | public Object getBean(String beanName){ 91 | return getApplicationContext().getBean(beanName); 92 | } 93 | } 94 | ``` 95 | 96 | 97 | 98 | **继承自抽象类WebApplicationObjectSupport** 99 | 100 | 类似ApplicationObjectSupport 的方法。调用getWebApplicationContext()获取WebApplicationContext 101 | 102 | 103 | 104 | **实现接口ApplicationContextAware** 105 | 106 | 实现该接口的setApplicationContext(ApplicationContext context)方法,并保存ApplicationContext 对象。Spring初始化时,扫描到该类,就会通过该方法将ApplicationContext对象注入 107 | 108 | ```java 109 | /** 110 | * @description: Spring Bean 对象工具 111 | * @author: husy 112 | * @date 2020/1/13 113 | */ 114 | @Component 115 | public class SpringBeanUtil implements ApplicationContextAware { 116 | private static ApplicationContext applicationContext; 117 | @Override 118 | public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { 119 | SpringBeanUtil.applicationContext=applicationContext; 120 | } 121 | 122 | public static T getBean(String beanName) { 123 | if(applicationContext.containsBean(beanName)){ 124 | return (T) applicationContext.getBean(beanName); 125 | }else{ 126 | return null; 127 | } 128 | } 129 | 130 | public static Map getBeansOfType(Class baseType){ 131 | return applicationContext.getBeansOfType(baseType); 132 | } 133 | } 134 | ``` 135 | 136 | 137 | 138 | # Bean的创建方式 139 | 140 | * 通过构造方法创建对象(默认) 141 | * 通过静态工厂创建对象(必须要有静态方法) 142 | * 通过实例工厂创建对象--先实例工厂,再创建对象 143 | 144 | 145 | 146 | **构造方法创建对象** 147 | 148 | ```xml 149 | 150 | ``` 151 | 152 | 153 | 154 | **静态工厂创建对象** 155 | 156 | ```xml 157 | 158 | ``` 159 | 160 | ```java 161 | public class StaticBeanFactory { 162 | public static ClientService createInstance() { 163 | return clientService; 164 | } 165 | } 166 | ``` 167 | 168 | 169 | 170 | **实例工厂创建对象** 171 | 172 | ```xml 173 | 174 | 175 | 176 | ``` 177 | 178 | ```java 179 | public class InstanceBeanFactory { 180 | public AccountService getBean(){ 181 | return new AccountServiceImpl(); 182 | } 183 | } 184 | ``` 185 | 186 | -------------------------------------------------------------------------------- /Web/Spring(3)事务管理.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | Spring事务的其实就是数据库对事务的支持,使用JDBC的事务管理机制,就是利用java.sql.Connection对象完成对事务的提交 4 | 5 | 事务是指在一系列的数据库操作过程中,一旦其中某一个动作出现错误,可以进行全部回滚,让系统将事务中对数据库的所有已完成的操作全部撤消,滚回到事务开始的状态,避免出现由于数据不一致而导致的接下来一系列的错误。 6 | 7 | 事务的出现是为了**确保数据的完整性和一致性**,在实际开发中,事务管理是必不可少的。 8 | 9 | 10 | 11 | # 事务基础 12 | 13 | ## 事务有四大特性(ACID) 14 | 15 | * **原子性(Atomicity)**:事务是一个原子操作,由一系列动作组成。事务的原子性确保动作要么全部完成,要么完全不起作用。 16 | * **一致性(Consistency)**:事务在完成时,必须是所有的数据都保持一致状态。 17 | * **隔离性(Isolation)**:并发事务执行之间无影响,在一个事务内部的操作对其他事务是不产生影响,这需要事务隔离级别来指定隔离性。 18 | * **持久性(Durability)**:一旦事务完成,数据库的改变必须是持久化的。 19 | 20 | 21 | 22 | ## 事务并发问题 23 | 24 | 在企业级应用中,多用户访问数据库是常见的场景,这就是所谓的事务的并发。事务并发所可能存在的问题: 25 | 26 | * **脏读**:一个事务读到另一个事务未提交的更新数据。 27 | * **不可重复读**:一个事务两次读同一行数据,可是这两次读到的数据不一样。 28 | * **幻读**:一个事务执行两次查询,但第二次查询比第一次查询多出了一些数据行。 29 | * **丢失更新**:撤消一个事务时,把其它事务已提交的更新的数据覆盖了。 30 | 31 | 32 | 33 | # Spring事务 34 | 35 | Spring事务管理的核心接口是PlatformTransactionManager ;事务管理器接口通过getTransaction方法根据指定的传播行为返回当前活动的事务或创建一个新的事务,这个方法里面的参数是TransactionDefinition类,这个类就定义了一些基本的事务属性。 36 | 37 | ![](./Spring(3)事务管理/1120165-20171003112557490-1092711802.png) 38 | 39 | 在TransactionDefinition接口中定义了它自己的传播行为和隔离级别 ,源码如下: 40 | 41 | ```java 42 | public interface TransactionDefinition { 43 | int PROPAGATION_REQUIRED = 0; 44 | int PROPAGATION_SUPPORTS = 1; 45 | int PROPAGATION_MANDATORY = 2; 46 | int PROPAGATION_REQUIRES_NEW = 3; 47 | int PROPAGATION_NOT_SUPPORTED = 4; 48 | int PROPAGATION_NEVER = 5; 49 | int PROPAGATION_NESTED = 6; 50 | int ISOLATION_DEFAULT = -1; 51 | int ISOLATION_READ_UNCOMMITTED = 1; 52 | int ISOLATION_READ_COMMITTED = 2; 53 | int ISOLATION_REPEATABLE_READ = 4; 54 | int ISOLATION_SERIALIZABLE = 8; 55 | int TIMEOUT_DEFAULT = -1; 56 | 57 | int getPropagationBehavior(); 58 | int getIsolationLevel(); 59 | int getTimeout(); 60 | boolean isReadOnly(); 61 | @Nullable 62 | String getName(); 63 | } 64 | ``` 65 | 66 | 67 | 68 | 69 | 70 | ## Spring传播途径 71 | 72 | **以下途径支持当前事务** 73 | 74 | 1. propagation_required:默认,表示当前必须有事务;当前有事务,则支持当前事务,如果不存在 就新建一个 75 | 2. propagation_supports:表示支持当前事务;如果不存在,就不使用事务 76 | 3. propagation_mandatory:支持当前事务,如果当前事务不存在,抛出异常 77 | 78 | **以下途径不支持当前事务** 79 | 80 | 1. propagation_requires_new:表示新建一个事务,也就是说,如果当前没有事务则新建一个,就算有,也挂起当前事务,新建一个的事务, 81 | 2. propagation_not_supported:表示不支持当前事务;如果有事务存在,挂起当前事务 ,没有则以非事务方式运行 82 | 3. propagation_never:表示不要事务,以非事务方式运行;如果有事务存在,就抛出异常 83 | 4. propagation_nested:表示嵌套事务;如果当前存在事务,则在嵌套事务内执行。(换句话说就是,他的提交是要等和他的父事务一块提交的,父回滚他回滚);如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。 84 | 85 | ## Spring事务的隔离级别 86 | 87 | 1. **ISOLATION_DEFAULT**:默认隔离级别,使用数据库默认的事务隔离级别 88 | 2. **ISOLATION_READ_UNCOMMITTED**:未提交读;充许另外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻读。这是事务最低的隔离级别 89 | 3. **ISOLATION_READ_COMMITTED**:提交读(Oracle\sqlserver 默认),保证一个事务修改的数据提交后才能被另外一个事务读取 90 | 4. **ISOLATION_REPEATABLE_READ**:可重复读(Mysql 默认);这个事务不结束,别的事务就不可以改这条记录,加锁;这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。 91 | 5. **SERIALIZABLE**(serializable):串行化(级别最高),花费最高代价。事务被处理为顺序执行,运行完一个事务的所有子事务之后才可以执行另外一个事务,有效的防止脏读,不可重复读 和幻读。 92 | 93 | 94 | 95 | # 配置事务管理器 96 | 97 | Spring提供了两种事务管理的方式:编程式事务管理和声明式事务管理 98 | 99 | ## 编程式事务管理 100 | 101 | 编程式事务管理我们可以通过PlatformTransactionManager实现来进行事务管理,同样的Spring也为我们提供了模板类TransactionTemplate进行事务管理,下面主要介绍模板类,我们需要在配置文件中配置 102 | 103 | ```xml 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | ``` 116 | 117 | 118 | 119 | ## 声明式事务管理 120 | 121 | 声明式事务管理有两种常用的方式,一种是基于tx和aop命名空间的xml配置文件,一种是基于@Transactional注解,随着Spring和Java的版本越来越高,大家越趋向于使用注解的方式 122 | 123 | ### **基于tx和aop命名空间的xml配置文件** 124 | 125 | ```xml 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | ``` 140 | 141 | ### **基于@Transactional注解** 142 | 143 | 开启对注解事务管理的支持 144 | 145 | ```xml 146 | 147 | 148 | ``` 149 | 150 | 在需要事务管理的地方加上@Transactional注解,如: 151 | 152 | ```java 153 | @Transactional(rollbackFor=Exception.class) 154 | public void insert(String sql, boolean flag) throws Exception { 155 | dao.insertSql(sql); 156 | // 如果flag 为 true ,抛出异常 157 | if (flag){ 158 | throw new Exception("has exception!!!"); 159 | } 160 | } 161 | ``` 162 | 163 | -------------------------------------------------------------------------------- /Web/Spring(3)事务管理/1120165-20171003112557490-1092711802.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/husying/JNotes/91b51e6471e079615bed899a68a4008bfae1368c/Web/Spring(3)事务管理/1120165-20171003112557490-1092711802.png -------------------------------------------------------------------------------- /Web/Spring(5)MVC.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Spring MVC是Spring提供的一个强大而灵活的web框架,基于Java的实现了MVC设计模式 6 | 7 | Spring MVC主要由DispatcherServlet、处理器映射、处理器(控制器)、视图解析器、视图组成。通过将web层进行职责解耦,把复杂的web应用分成逻辑清晰的几部分,简化开发,减少出错,方便组内开发人员之间的配合。 8 | 9 | 10 | 11 | # SpringMVC工作原理 12 | 13 | 1. 客户端提交请求 -> DispatcherServlet:客户端请求发送到前端控制器,但前端控制自身不处理请求 14 | 2. DispatcherServlet -> HandlerMapping:前端控制器将请求调用处理器映射器进行解析,并将对象返给前端控制器; 15 | 3. DispatcherServlet -> HandlerAdapter:前端控制器将请求调用处理器适配器 16 | 4. HandlerAdapter -> Controller:处理器适配器去执行Controller并得到ModelAndView(数据和视图),并层层返回给前端控制器 17 | 5. DispatcherServlet -> ViewResolver:前端控制器调用视图解析器对 ModelAndView 进行解析为具体的View; 18 | 6. View -> 渲染,View会根据传进来的Model模型数据进行渲染,此处的Model实际是一个Map数据结构; 19 | 7. DispatcherServlet返回响应给客户端 20 | 21 | 22 | 23 | # SpringMVC核心组件 24 | 25 | **DispatcherServlet** 26 | 27 | 前端控制器,是整个Spring MVC的核心,负责接收HTTP请求组织协调Spring MVC的各个组成部分,DispatcherServlet的存在降低了组件之间的耦合性。 28 | 29 | **HandlerMapping** 30 | 31 | 映射处理器,负责根据用户请求找到Handler即处理器,Spring MVC 提供了不同的映射器实现不同的映射方式,例如:配置文件方式,实现接口方式,注解方式等。 32 | 33 | **HandlAdapter** 34 | 35 | 处理适配器,通过HandlerAdapter对处理器进行执行,这是适配器模式的应用,通过扩展适配器可以对更多类型的处理器进行执行。 36 | 37 | **Handler** 38 | 39 | Handler是继DispatcherServlet前端控制器的后端控制器,在DispatcherServlet的控制下Handler对具体的用户请求进行处理。 40 | 41 | **ViewResolver** 42 | 43 | ViewResolver负责将处理结果生成View视图,ViewResolver首先根据逻辑视图名解析成物理视图名即具体的页面地址,再生成View视图对象,最后对View进行渲染将处理结果通过页面展示给用户。 44 | 45 | **View** 46 | 47 | SpringMVC框架提供了很多的View视图类型的支持,包括:jstlView、freemarkerView、pdfView等。我们最常用的视图就是jsp。 48 | 49 | 50 | 51 | # SpringMVC和Struts2 区别 52 | 53 | * 拦截机制:Struts2 是类级别拦截,SpringMVC是方法级别的拦截。 54 | * 底层框架:Struts2 是采用过滤器实现的filter,springmvc 采用 servlet 实现的 55 | * 性能方面:Struts2 每次请求都会实例化一个Action;SpringMVC的Controller Bean默认单例模式 56 | * 配置方面:spring MVC和Spring是无缝的。从这个项目的管理和安全上也比Struts2高。 57 | 58 | 59 | 60 | # SpringMVC重定向和转发 61 | 62 | 转发:在返回值前面加"forward:",譬如"forward:user.do?name=method4" 63 | 64 | 重定向:在返回值前面加"redirect:",譬如"redirect:http://www.baidu.com" -------------------------------------------------------------------------------- /Web/Spring(6)注解.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 在Spring中的注解有很多,如下进行分类说明一下 6 | 7 | 8 | 9 | ### 用于标注组件 10 | 11 | @Controller:用于标注控制层组件 12 | 13 | @Service :用于标注业务层组件 14 | 15 | @Repository:用于标注数据访问组件,即DAO组件。 16 | 17 | @Component:泛指组件,当组件不好归类的时候,我们可以使用这个注解进行标注。 18 | 19 | @Configuration :声明当前类是一个配置类 20 | 21 | 22 | 23 | ### 用于依赖注入 24 | 25 | @Autowired 默认按类型装配,如果我们想使用按名称装配,可以结合@Qualifier注解一起使用。 26 | 27 | @Qualifier("personDaoBean") 按名称装配,如下:@Autowired + @Qualifier("personDaoBean") 存在多个实例配合使用 28 | 29 | @Resource 默认按名称装配,当找不到与名称匹配的bean才会按类型装配。 30 | 31 | @Inject :(不常用)根据类型进行自动装配,按名称装配需要@Named结合使用时 32 | 33 | 34 | 35 | **Autowired 和 Resource 的区别** 36 | 37 | @Autowired 默认按照byType方式进行bean匹配, 38 | 39 | @Resource 默认按照byName方式进行bean匹配,找不到再按type去匹配 40 | 41 | @Autowired是Spring的注解,@Resource是J2EE的注解,建议使用@Resource注解,以减少代码和Spring之间的耦合。 42 | 43 | 44 | 45 | ### 用于控制层 46 | 47 | **@RequestMapping**:映射多请求地址,作用于控制器类或其方法级别 48 | 49 | **@RequestParam**:将请求的参数同处理方法的参数绑定 50 | 51 | **@PathVariable**:用来处理动态的 URI,URI 的值可以作为控制器中处理方法的参数,可以使用正则表达式 52 | 53 | **@RequestBody**:作用在形参列表上,用于将前台发送过来固定格式的数据【xml 格式或者 json等】封装为对应的 JavaBean 对象 54 | 55 | **@ReponseBody**:方法将数据转为 json 数据直接写入 HTTP response body 56 | 57 | 注意:@RequestMapping 可用@GetMapping、@PostMapping、@PutMapping、@DeleteMapping、@PatchMapping 替代,这5种 是指用相应的请求方式进行映射 58 | 59 | 60 | 61 | ### 用于AOP 注解 62 | 63 | @Aspect 声明一个切面 64 | 65 | @After、@Before、@Around 定义建言(advice),可直接将拦截规则(切点) 作为参数 66 | 67 | @PointCut 定义拦截规则 68 | 69 | @EnableAspectAutoProxy 表示开启AOP代理自动配置,如果配@EnableAspectJAutoProxy表示使用cglib进行代理对象的生成 70 | 71 | 72 | 73 | ### 用于多线程注解 74 | 75 | @EnableAsync 注解开启异步任务支持 76 | 77 | @Async 声明该方法是个异步方法 78 | 79 | 80 | 81 | ### 用于定时任务注解 82 | 83 | @EnableSching 开启计划任务支持 84 | 85 | @Scheduled 声明一个计划任务 86 | 87 | 88 | 89 | ### 其他 90 | 91 | @Transcational 事务处理 92 | 93 | @Cacheable 数据缓存 94 | 95 | @Async异步方法调用 96 | 97 | @SpringBootApplication 申明启动类 98 | 99 | @AliasFor 用于属性限制 100 | 101 | @ComponentScan 102 | 103 | @PostConstruct 用于指定初始化方法(用在方法上) 104 | 105 | @PreDestory 用于指定销毁方法(用在方法上) 106 | 107 | @DependsOn:定义Bean初始化及销毁时的顺序 108 | 109 | @Primary:自动装配时当出现多个Bean候选者时,被注解为@Primary的Bean将作为首选者,否则将抛出异常 110 | 111 | @PreDestroy 摧毁注解 默认 单例 启动就加载 --------------------------------------------------------------------------------