0%

了解Redis通信内容

Redis我们都比较熟悉,可以用来做缓存、分布式锁等,但是,其中的客户端与服务端是如何进行通信的呢?

我们可以分别模拟一个服务端或者客户端,打印查看来自实际连接的请求来获取它们的通信方式

首先,让我们先使用先模拟一个服务端,使用Jedis进行连接查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 一个简单的demo
public class MockRedisServer {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(6379);
Socket socket = serverSocket.accept();
try (InputStream inputStream = socket.getInputStream();
final OutputStream outputStream = socket.getOutputStream()) {
byte[] data = new byte[1024];
final int read = inputStream.read(data);
final byte[] bytes = Arrays.copyOf(data, read);
System.out.println(new String(bytes));
}
}
}
阅读全文 »

什么是 Lambda表达式?

对于 Java 中的 lambda 表达式,我们可以把它简单的理解为一个函数。

比如,我们需要这样一个函数,它需要把两个数字相加,将结果返回 则可以这样定义

1
int add(int a, int b);

但是我们知道,Java中函数是没有办法单独定义存在的,所以我们需要一个接口才能声明这个函数功能

1
2
3
interface Function {
int add(int a, int b);
}

当我们需要实现这个方法的时候,一种方法就是定义一个新的类来实现这个接口

1
2
3
4
5
6
class Calc implements Function {
@Override
public int add(int a, int b) {
return a + b;
}
}
阅读全文 »

接着之前说过的 Java HashMap的Rehash,这次我们来看看 Redis中的 hash结构(对应Java中的Map)是如何实现rehash的。

这次先说下结论,它的结构与HashMap基本一致,只是它有两个哈希表,平时只使用其中的第一个,在发生rehash时,会逐渐的将元素转移到另一个表中,全部转移完成后,再将引用赋值给第一个哈希表

下面我们来开始看代码

阅读全文 »

我们都知道Java中的HashMap是使用数组,结合链表来实现的,其结构如下:

如果加入的元素数量达到了设定的阈值,那么必然会涉及到扩容重新分配空间,将元素重新插入到新的空间中,也就是发生了rehash。这个过程其实是很耗时的,这也是为什么我们写代码时,最好指定的HashMap的初始空间大小的原因,就是为了避免或者减少发生rehash的次数。下面我们来看看这个过程的具体实现。

JDK是一直在升级的,其中的代码也在不断优化调整,我们这次主要就看下JDK1.7JDK1.8中的实现

阅读全文 »

这篇来跟踪一下AbstractBeanFactory#getBean(java.lang.String, java.lang.Class<T>)这个方法获取bean实例的流程,由于过程比较复杂,我们这里以一个简单的例子来跟进一下主要的流程

Spring 配置使用

下面我们看下具体的例子代码

spring配置文件

1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean class="com.zavier.spring.beans.TestBean"
id="testBean" init-method="myinit" destroy-method="mydestroy">
</bean>

</beans>
阅读全文 »

spring-beans虽然是一个很基础的包,但是它已经包括了很多的功能,我们先看下如何在只使用spring-beans包的情况下,解析并拿到xml中配置的bean实例

spring-bean.xml

1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean class="com.zavier.spring.beans.SimpleBean" id="simpleBean" />

</beans>

解析代码

1
2
3
4
5
6
7
8
9
// 1.创建一个BeanFactory
DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
// 2.创建读取Bean定义的Reader
XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
// 3.使用Reader来读取指定的资源信息
ClassPathResource resource = new ClassPathResource("spring-bean.xml");
beanDefinitionReader.loadBeanDefinitions(resource);
// 4.之后就可以从工厂中正常获取对应的bean实例
SimpleBean bean = beanFactory.getBean(SimpleBean.class);
阅读全文 »

MyBatis 基本用法

MyBatis是我们常用的ORM框架,先看一下它的基本用法(省略了Mapper相关的配置项):

1
2
3
4
5
6
7
8
9
10
11
12
// 读取MyBatis配置文件
InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
// 从配置文件中构建 SqlSessionFactory (全局只有一个,用于构建 SqlSession)
SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
// 使用 SqlSessionFactory 创建 SqlSession(请求作用域,用后销毁)
SqlSession session = sessionFactory.openSession(true);
// 获取对应 Mapper
UserMapper mapper = session.getMapper(UserMapper.class);
// 执行查询
User user = mapper.findById(1);
// 关闭 session
session.close();

MyBatis-Spring

工作中最常用的还是与Spring结合,使用mybatis-spring

1
2
3
4
5
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.1</version>
</dependency>
阅读全文 »

CountDownLatch功能很简单,它主要有两个方法,await()countDown(),初始创建的时候需要给它提供一个数值,调用countDown()方法会将数值减1,调用await()方法的时候会判断值是不是等于0,如果等于0就继续执行,否则就阻塞等待

1
2
3
4
5
6
// 初始化创建,值为1
CountDownLatch countDownLatch = new CountDownLatch(1);
// 如果countDownLatch中的值不是0则阻塞等待
countDownLatch.await();
// 将countDownLatch中的值进行减1
countDownLatch.countDown();

利用这两个方法,我们能用来做什么呢?

阅读全文 »

工作流程

AbstractQueuedSynchronizer 是一个用于在竞争资源(如多线程)时使用的同步器,它内部使用了一个int类型的字段status表示需要同步的资源状态, 并基于一个先进先出(FIFO)的等待队列,队列中的每个节点表示要获取资源的线程

同步器主要是用于控制资源的获取以及释放,它可以用于独占模式和共享模式,这里我们以独占模式为例

在获取和释放资源时,我们需要实现自己的尝试获取和尝试释放的方法,利用status字段来控制成功与否

阅读全文 »

Redis支持的主要有5种数据类型,string, list, set, zset , hash,但是对于每种数据类型,Redis都不是简单的使用一种数据结构来实现,而是根据数据量等因素使用多种数据结构(SDS、双向链表、hashtable等),来达到提高效率、节省空间的目的,可以使用object encoding <key> 来查看数据的内部结构

阅读全文 »