IO与NIO
IO与NIO我们都知道IO流传输,其实IO模型有很多,例如BIO、NIO、AIO等,传统的IO都是同步的 IO为各种流操作 IO操作分类 I IO操作分类 II 其中,输入流可以为InputStream和Reader,分别为字节流和字符流,对应地,输出流为OutputStream和Writer,具体的使用在此不详述 NIO是IO模型中后推出的新IO模型 NIO并不一定是多线程的,但是NIO是多管道的,利用缓冲作为中间介质进行数据传输,运用的其实是多路复用技术,它恰恰是通过减少线程数量从而减少上下文的频繁切换,提高性能 Channel:通道,相当于一个连接,不能直接输出数据,只能与Buffer交换数据

2019-05-11鱼鱼
算法:广度优先搜索(BFS)(最短路径)
算法:广度优先搜索(BFS)(最短路径)我们先看一个案例: 遍历一个树结构,按层次输出树的节点内容,即:欲求 A B C D E F 实现方式便是从根节点(A)向下遍历,先获取A,其次是A的子节点B和C,其次是B的子节点D…… 这种遍历树结构或者图结构的方法被称作广度优先搜索(BFS),与之对应的先遍历到最下层子节点的是深度优先 BFS核心采用队列的数据结构,例如上面的树结构中,解法为: A进队列->A出队列 B、C进队列->B出队列 D进队列 ->C出队列 E、F进队列-> D、E、F出队列 如果想要区分层次边缘,使用count参数即可 解法步骤(蓝色部分为已经处理完的节点):

2020-06-05鱼鱼
分布式系统中的CAP原则与BASE原则
分布式系统中的CAP原则与BASE原则没有十全十美的分布式系统,分布式的痛点就在于各个节点状态的统一,CAP和BASE便是描述它的状态 本文中的分布式系统不仅指一套全是无状态的应用的服务系统,单纯依靠共享资源(如多个无状态的服务共用数据库或NoSQL而不在内存或是本身的服务容器中存储任何数据)运转的服务不是纯粹的分布式系统,分布式系统中一般需要包含有状态的服务(如主从同步的Mysql、多机哨兵模式的Redis、设置会话共享的分布式Tomcat服务) 图A 分布式架构雏形 ( 试想在上图中,若是网关通过A分区对数据做出了修改,此时还没有写入数据库但是A分区的缓存做出了调整,在分区容错的情况下A不能直接与B通信,那A与B分区就会失去一致性

2019-09-29鱼鱼
使用RPC与Restful接口调用服务
使用RPC与Restful接口调用服务在SOA和微服务架构中,远程通信是无法避免的,最常用的远程通信有两种方式: restful的接口,使用Http通信 使用dubbo或是Spring Cloud组件进行 RPC协议远程调用,可选地使用socket通信 不同的人对 RPC调用会有不同的看法,甚至对rpc本身的理解都不甚相同,但我认为 RPC有两种倾向: 一为语义化的 RPC 没有统一的请求规范,数据格式在开发人员中很难达成一致,在使用传统Http调用时,交互的双方需要约定一份“API文档”以保证数据格式的唯一性,这样API格式本身就成为了一道大墙,耽误研发双方的时间 但如果服务间采用语义化 RPC进行交互,双方可能并不需要一份文档,只要一份约定好的代码,并以此作为双方的依赖,在请求时也仅仅是直接调用方法本身,如此强的语义性怎能让人不爱

2021-01-13鱼鱼
MySQL tips
MySQL tips一些日常接触到的MySQL优化tips,比较散乱 假设有一个用户表,对于一句很简单的查询语句: 假设name与age字段均有单列索引,容易想到的是,MySQL应该会分别走两次索引,并将其结合起来,EXPLAIN也是如此,大多数时候MySQL会进行优化,我们可能会看到EXPLAIN的结果中有Using union或Using soft union,这是MySQL针对OR做了隐性的优化,但当SQL复杂或数据极端情况下,这一语句极容易变成全表扫描,偶尔使用联合索引可能解决问题,更多情况则是MySQL“昏了头”,即使OR条件均涉及数据条数不多,依旧没能在查询语句中使用索引,此时应调整为UNION语句(可以权衡一下重复及顺序是否有影响,可以使用更快的UNION ALL):

2021-01-13鱼鱼
排坑指南-异步操作HttpServletRequest丢失Cookie
排坑指南-异步操作HttpServletRequest丢失Cookie遇到了一个很奇怪的bug:请求鉴权失败,因为通过Request对象获取到的Cookie中没有数据 经过debug调用request.getCookies()方法返回了null值,但是header属性的cookie却能拿到用户的有效cookie(request.getHeader("cookie")),其中缘由,且慢慢道来 我们可以在web项目中通过Request对象很方便的获取Cookie对象: 但其内部实现其实有一层缓存逻辑,从名为"cookie"的请求头中读取并处理数据转为Cookie对象并不是个省时事,在org.apache.catalina.connector.Request类中可以看到如下代码实现:

2020-11-11鱼鱼
Java中的动态代理与静态代理
Java中的动态代理与静态代理proxy(代理)作为一种设计模式在Java中已经应用非常广泛,例如常见的拦截器是代理模式设计的,AOP是通过动态代理实现的,而基于AOP的应用就更多了,从简单的事务应用到Dubbo框架,Java开发中离不开代理,本篇文章主要阐述Java中的代理,此处是比较狭义的代理,仅指方法和类中的代理 代理模式是一种非常常见的设计模式,它通过给某对象提供代理,从而通过代理对象控制原对象的引用 以下是代理模式的简单实现: 类Admin: 对应的代理类AdminProxy: 设计良好的聚合代理模式应该是代理类与被代理类共同继承一个接口,此处只为实现功能 这样在执行new AdminProxy().changeWorld()时,除了会调用原本的new Admin().changeWorld(),在方法前后也可以做出些其他的操作
![Java中的动态代理与静态代理]()
2019-08-09鱼鱼
ELK实战(Ⅰ) 基于ELK整合分布式业务日志
ELK实战(Ⅰ) 基于ELK整合分布式业务日志大多情况下,我们可能都习惯了使用linux指令查看日志,很多时候一句简简单单的tail、grep能定位绝大多数问题 但是面临复杂的目录结构和分布式系统产生的“分布式日志文件”,如果还要我们一个一个去查日志,就会耗费很多没必要的时间 可以利用ELK这套组件快速搭建一个日志系统 注意此文仅针对可能很多情况下格式不确定的业务日志,对于某些组件日志我们有更好的可视化实践方式,可以参考此系列的其他文章 对于一个日志系统,我们要确认我们的诉求,在不同的场景下采用不同的收集方式: 是否是分布式系统需要合并多个节点的日志 如果需要,则需要用分布式组件收集并合并日志,这也是一个日志系统最基本的要求;

2020-03-14鱼鱼
Java的socket通信
Java的socket通信网络编程中,会使用socket通信 TCP/IP协议,即Transmission Control Protocol/Internet Protocol,传输控制协议/网际协议,他使用TCP/IP四层模型(实际开发中只涉及到四层模型,软件范畴涉及不到OSI七层参考模型): TCP是面向连接的通信协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接的所以只能用于端到端的通讯 具有高度的可靠性 三次握手,即通信时,客户端和服务端共计要传输三次包,三次握手建立连接: 1.主机(客户端)发送 SYN=1(建立连接标识)和seq=x(序号),客户端进入SYN_SEND状态,等待服务端确认

2019-03-27鱼鱼
多线程应用提高(II) 线程池
多线程应用提高(II) 线程池项目中,当发生并行操作时,一般都会用到线程池处理多线程任务,线程池的规则类似于数据库连接池,在此不予赘述 jdk自带线程池,此处主要讲述Spring框架自带的线程池ThreadPoolTaskExecutor 通过实现Runnable和Callable接口实现一个线程任务,从而能放入Executor进行线程管理 其中,Callable可以理解为带有返回值的Runnable,并且Callable需要实现的方法不是run()而是call(),该方法返回一个泛型对象 当我们把一个需要返回值的线程任务放进线程池后,线程池会返回一个Future对象,借助该对象,我们可以调用get()方法获取线程的状态,调用get()会阻塞当前线程直到返回结果

2020-02-25鱼鱼
安全框架的使用:Shiro
安全框架的使用:ShiroShiro与Sping Security均是java的安全框架,主要用于处理用户身份验证和授权 常见场景为用户系统登录 Shiro易用性强,提供了认证,授权,加密,和会话管理功能 Shiro的三大核心组件 : Subject:即当前用户概念,不止代表着某用户,也可以是进程或任何可能的事物 SecurityManager:即所有Subject的管理者,可以把他看做是一个Shiro框架的全局管理组件,用于调度各种Shiro框架的服务 作用类似于SpringMVC中的DispatcherServlet,用于拦截所有请求并进行处理 Realm:Realm是用户的信息认证器和用户的权限认证器,我们需要自己来实现Realm来自定义的管理我们自己系统内部的权限规则

2019-09-29鱼鱼
对多线程的执行效率探究——合理的任务并发拆分
对多线程的执行效率探究——合理的任务并发拆分通常,我们选择多线程执行任务有两个理由,一是复杂任务采用多线程处理能够在发生并发时让用户减少等待也能防止阻塞,一是充分利用空闲时间,提高任务处理的效率,就后者而言,此处探讨不考虑客户端并发是否有必要把一个任务拆分成多线程来处理 为了探究多线程的效率问题,我做了一个实验,将不同种类的任务分别用单线程和多线程执行,同时也试验了不同种类的锁机制 测试基于Java 8的版本,希望看到总结可以直接点击到文末 开启五个线程执行任务,设定了足够次数的循环输出,输出的数字和当前线程,利用System.currentTimeMillis()统计任务用时 (代码略)以下是相同任务在不同环境下执行多次的平均执行时间

2019-12-09鱼鱼