RabbitMQ的工作模式

RabbitMQ常用的有6种工作模式,它们分别是简单模式,work模式,发布订阅模式,路由模式,Topic模式。下面就分别解释一下这些工作模式的特点和实现方式。

mybatis源码分析一

我们从最简单的一段代码开始,分析清楚mybatis的大致工作流程。然后再从代码细节上分析mybatis的一些特性。 基础代码示例1234567891011121314151617public class test { public static void main(String[] args) throws IOException{ String resource = "example/mybatis-config.xml"; // 加载配置文件 并构建SqlSessionFactory对象 InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory factory = new SqlSessionFactoryBuilder().build(inputStream); // 从SqlSessionFactory对象中获取 SqlSession对象 SqlSession sqlSession = factory.openSession(); // 执行操作 User user=new User(); user.setId(1); Object u= (User)sqlSession.selectOne("getUser", user); System.out.println(u.toString()); // 关闭SqlSession sqlSession.close(); }}

CyclicBarrier源码分析

概述CyclicBarrier是一个同步辅助类,它允许一组线程相互等待,直到达到某个公共屏障点。并且在释放等待线程之后,CyclicBarrier是可以重复使用的。

CountDownLatch源码分析

概述CountDownLatch允许一个或多个线程等待直到在其他线程中执行的一组操作完成的同步辅助。简单来说,就是CountDownLatch内部维护了一个计数器,每个线程完成自己的操作之后都会将计数器减一,然后会在计数器的值变为0之前一直阻塞,直到计数器的值变为0.

ReentrantReadWriteLock源码分析

概述ReentrantReadWriteLock维护了一对相关的锁,它们分别是共享readLock和独占writeLock。关于共享读锁和排他写锁的概念其实很好理解。所谓共享读锁就是一个线程读的时候,其它线程也可以来读(共享),但是不能来写。排他写锁是指一个线程在写的时候,其它线程不能来写或读(排他)。除了这个特点之外,ReentrantReadWriteLock还有一个特点就是可重入的。它和ReentrantLock一样都是支持Condition的。而且ReentrantReadWerite还支持锁降级,即允许将写锁降级为读锁。

ReentrantLock源码分析

概述ReentrantLock是一个可重入的互斥锁,也被称为独占锁。它支持公平锁和非公平锁两种模式。

Spring Bean的加载流程

Bean加载的总体流程以这行代码为起点,探究这背后到底经历了什么? 1MyTestBean bean=(MyTestBean)bf.getBean("MyTestBean"); 调用getBean("MyTestBean")背后实际是调用了doGetBean(name,null,null,false)doGetBean方法。这个方法干的事情有些多,但总结起来就这们几步: 通过传入的的name参数,提取beanName属性.这个地方有可能会有疑问,传入的name不就是bean的Name吗。其实不然,因为spring还允许有别名。 尝试使用直接从缓存获取,或者sinletionFactories中的ObjectFactory中获取,具体的也就是在Object sharedInstance = getSingleton(beanName);代码中。这里的缓存其实就是指DefaultSingletonBeanRegistry类中的singletonObjects:Map。这个缓存就是一个ConcurrentHashMap其中键为BeanName,值就是对应的Bean。

Redis设计与实现读书笔记二

redis服务器redis服务器负责与多个客户端建立网络连接,处理客户端发送的命令请求,在数据库中保存客户端执行命令所产生的数据,并通过资源管理器来维持服务器自身的运转。 命令请求的过程加入我们使用了这样一天个命令 12redis> SET KEY VALUEOK 整个执行的流程 客户端会将命令转换为协议格式,然后通过连接到服务器的套接字按协议格式的命令请求发送给服务器。 当客户端与服务器之间连接的套接字变得可读时,服务器调用命令求情处理器。 读取套接字中协议格式的命令,将它保存到客户端状态的输入缓冲区里。 对输入缓冲区中的数据进行分析,将请求参数存入argv中,参数个数保存在argc中。 根据请求参数(查找命令表),调用相应的命令执行器,执行指定的命令(在正式执行之前还会检测出参数个数是否正确,客户端是否通过身份认证,如果服务器打开了maxmenory功能,那么在执行命令之前,先检查服务器的内存占用情况,并在需要时进行内存回收,之后再进行执行,并且服务器没被阻塞)。 再实现函数调用之后,还会执行一系列的后续工作,比如检查是否需要记录到慢查询日志,更新命令的redisCommand结构的milliseconds属性,并将器calls属性加一,如果开启了AOF持久化功能,那么将刚才的命令写入到AOF缓冲区中,如果有其它服务器正在复制这个服务器,那么服务器会见刚刚执行的命令传播到所有从服务器。

Redis设计与实现读书笔记一

简单动态字符串Redis没有直接使用C语言中的以空字符结尾的字符串。而是自己构建了一种名为简单动态字符串(SDS)的抽象类型。Redis中直接使用C字符串的地方仅仅是那些不需要对字符串进行修改的地方,作为字面量使用。Redis底层使用了大量的SDS。比如set msg "hello world",这个命令会建立一个键值对,Redis会为msg创建一个SDS,为’hello world’创建一个键值对。 SDS的定义12345struct sdshdr{ int len; //记录buf中已经使用的字节数,等于SDS所保存的字符串的长度 int free; //记录buf中空闲的字节的数量 char buf[]; //字节数组,用于保存字符串}

Redis实战学习笔记二

使用Redis构建支持程序案例一: 使用Redis实现日志的记录需求: 在构建应用程序和服务的过程中,对正在运行的系统的相关信息进行挖掘变得越来越重要。这都依赖于日志。 分析: 许多日志的记录的方式都是将日志记录到文件中去,然后随着时间的流逝新建日志文件(因为日志文件大大小不可能无限的增长),因为每个服务都有相应的日志记录,并且每种服务的日志轮换机制也是不同的,这就会缺少了一种将这些日志聚合的方案。还有一种日志记录方式是利用syslog服务来进行日志的记录。syslog服务接收各个服务的日志信息,并路由到不同的磁盘上,它还负责日志的轮换和删除工作。它要比直接写文件方便的多。 我们也可以利用Redis来实现日志的记录。 实现方式: 12345678910111213141516171819202122SEVERITY={ # 设置一个字典,将日志的安全级别映射为字符串 loggin.DEBUG:'debug', loggin.INFO:'info', loggin.WARNING:'warning', loggin.ERROR:'error', loggin.CRITICAL:'critical'}SERVERITY.update((name,name) for name in SERVERITY.values())def log_recent(conn,name,message,severity=loggin.INFO,pipe=None): # 将日志的安全级别映射为简单的字符串 severity=str(SEVERITY.get(severity,severity)).lower() # 创建负责存储消息的键 destination='recent:%s:%s'%(name,severity) # 在消息中添加当前时间 message=time.asctime()+' '+message # 使用流水线通信方式 pipe=pipe or conn.pipeline() pipe=lpush(destination,message) # 对日志列表进行修剪,只保留100条消息 pipe.ltrim(destination,0,99) # 执行两个命令 pipe.execute()

167891013