WebSocket长链接

项目中B端需要实时更新数据,这里记录下在SpringBoot下WebSocket长链接的开发过程。实时通知从最早的http轮训,然后到http1.1的Keep-Alive长链接机制,都是使用Request、Response机制。必须客户端主动发起请求,服务端才能响应。而WebSocket的机制是服务端可以主动向客户端推送消息。这种模式更加节约服务端资源,提高性能。

阅读更多

使用AbstractProcessor自动生成角色权限数据

项目开发中遇到一个关于RBAC中数据入库问题。权限主要包含页面权限,接口权限及数据权限。页面权限一般来讲是需要手动添加的,而接口权限则是通过swagger导入,或者手工录入,这样存在很多问题。比如接口书写不规范,运营看不懂。每次迭代,都需要手动角色绑定权限,这样人工错误率非常高。页面权限问题是没法解决的,但是我们可以解决接口权限问题。

阅读更多

Netty自带编解码器及自定义编解码器

上一篇文章Netty应用层处理粘包以及半包记录了使用Netty处理TCP粘包及半包。包含定长补齐,特殊字符分割,变长协议三种方案,并且使用了Netty自带的FixedLengthFrameDecoder定长解码器,StringDecoder字符串解码器,DelimiterBasedFrameDecoder特殊字符解码器,LengthFieldBasedFrameDecoder变长解码器LengthFieldPrepender编码器。本篇文章我们记录除了这些编解码器之外的Netty编解码器及自定义编解码器。针对Netty自带的编解码器,我们持续更新。

阅读更多

Netty应用层处理粘包以及半包

上一篇文章Netty初探记录了使用Netty开发Java NIO的过程,但是并没有处理TCP的粘包与半包。因为TCP是面向流的传输层协议,传输层并不处理粘包半包的任务,所以应用层必须处理粘包与半包的问题。本篇文章记录Netty处理粘包与半包。

阅读更多

Netty初探

上一章记录了Java NIO简单使用,其中提到了常见的几种IO多路复用模型,本章我们初试Netty,使用Netty写一个Netty客户端与服务端连接。简单的比较一下Java NIO与Netty NIO的区别。

阅读更多

NIO简单使用

之前总结了一篇BIO简单使用,BIO在长链接场景,一个连接占用一个线程。在短连接场景,虽然可以通过线程池优化,但是CPU会在不同的CPU不停的切换。因此BIO并不适用于高并发。Oracle在JDK1.4中引入了NIO的SDK,NIO与BIO不同之处在于NIO使用Linux中的IO多路复用技术。IO多路复用技术是将多个阻塞IO复用到同一个Selector阻塞上。本篇文章主要记录NIO的学习过程。

阅读更多

Java使用JNI调用动态链接库

项目中有个需求,需要根据用户上传的图片分析出用户的一些面部特征,血压,血氧等用户体征数据,Java层接收用户上传图片,保存,然后将图片地址传递给C++算法去处理,算法层计算出结果并返回给Java层一个对象。这里做个简单的demo模拟这个需求,大概需要的技术有C++,JNI Java等。

阅读更多

BIO简单使用

从本章开始,后面一段时间都学习网络和IO方面的知识。网络和IO都是知识盲区,慢慢整理,争取把这部分梳理清楚,首先IO是Input和Output的简写。代表输入和输出。而从位置来区分,又分为本地IO和网络IO。本地IO代表本机系统内的设备进行通信,网络代表本机系统和网络上的系统进行通信。而网络通讯模型又分为BIO(同步阻塞IO),NIO(同步非阻塞IO),AIO(异步非阻塞IO)。本章主要记录BIO的简单使用。

阅读更多

AQS分层及自定义锁

之前写了一些锁使用文章,比如ReentrantLock(独占锁),ReentrantReadWriteLock(读写锁)等,也写了一些线程通讯类Condition(条件队列),CountDownLatch(倒计时器),CyclicBarrier(循环栅栏),Semaphore(信号量)等,底层都是使用AQS实现的。本篇文章主要记录AQS内部变量方法的使用及作用,还使用AQS实现了自定义锁的实现。比较简单,如需编写复杂的自定义锁也可以参考ReentrantLock(独占锁),ReentrantReadWriteLock(读写锁)。

阅读更多

Condition原理解析

在之前介绍ReentrantLock锁使用文章中,简单的介绍了Condition在ReentrantLock中的使用,Condition主要用作线程之间的通信,等待,唤醒等功能,但是Condition是如何实现线程之间的通信的呢?本篇文章会罗列出所有Condition的API,然后介绍每个APi的功能并且描述Condition底层的实现原理。

阅读更多

ReentrantReadWriteLock原理解析

前面在介绍ReentrantLock提到过SHARED锁和EXCLUSIVE锁,我们使用ReentrantLock的时候,虽然因为自旋效率较高,但有些情况下我们不必要使用独占锁,比如读写场景,读较多,写较少,可以让多个线程同时取读,当有线程写的时候让其余的读写线程等待即可。这样提高了读的效率。ReentrantReadWriteLock从名字来看就是读写锁,读读共享,读写互斥。

阅读更多

CyclicBarrier使用

上一篇文章使用CountDownLatch模拟一家人出行旅行的计数器模型,也可以使用CyclicBarrier实现,CyclicBarrier翻译成英文为循环栅栏,CyclicBarrier的内部原理与CountDownLatch基本一样。不同地方在于CountDownLatch使用Node管理线程中断,而CyclicBarrier使用Condition队列。其实内部都一样。文章记录CyclicBarrier的使用过程以及其内部实现原理,供后续使用,复习,复盘等。

阅读更多

Semaphore使用

Semaphore是一个计数信号量,常用于限制可以访问某些资源(物理或逻辑的)线程数目。比如我们的接口只能同时有1000个连接访问,比如停车场只能停50辆车等等,Semaphore内部通过AQS实现公平锁和非公平锁。

阅读更多

CountDownLatch使用

项目开发中有一些需求,比如需要一些线程执行完成后再去执行一些操作。此时就需要用到CountDownLatch这个类,CountDownLatch是一个计数器,每当执行一个任务完成时调用计数器减一,直到count=0时才会执行后续的线程。CountDownLatch中的count不可重置。如果需要对count进行重置,官方建议使用CyclicBarrier,在后面的文章中会进行使用介绍。

阅读更多

ReentrantLock使用

之前有篇文章分析了Synchronized如何锁以及锁升级的过程,我们可以使用Synchronized来保证线程安全,为什么Java还设计一个AQS的东西来保证线程安全呢?我也不是特别清楚,一边读源码,一边梳理。本文主要记录ReentrantLock的使用及部分源码的梳理过程。

阅读更多

LongAdder及Striped64解析

Java原子类原理解析文章中写过一个原子的累加计算,AtomicInteger使用CAS的方法保证了原子性。也在ABA问题原理解析文章中阐述了关于AtomicInteger的ABA问题。以及如何解决ABA问题。那么有没有办法解决多线程对一个变量循环竞争导致的CPU空转。标题中的LongAdder就是解决方案之一。

阅读更多

ABA问题原理解析

AtomicReference使用

上一篇文章阐述了AtomicInteger如何保证线程安全,在Atomic包下还有AtomicLong,AtomicBoolean及相对应的数据包装类保证了线程安全,但是这些都是Java基础数据类型,如果需要操作的是一个自定义对象,就要使用到AtomicReference。它是一个可以自动更新的对象引用。

阅读更多

Java原子类原理解析

首先juca包下的原子类是线程安全的,那么JDK为什么会设计原子类呢,我觉得主要应该是为了解决包装类及基础数据多线程不安全,以及解决volatile只有有序性及可见性,没有原子性的问题。本篇文章主要记录juca包下的一些工具的使用及其原理。

阅读更多

上传文件ForkJoinPool多线程批量插入MySQL

对于ToG项目经常需要拿到Excel或Txt数据保存到MySQL中,因为解析Excel比较麻烦,这次使用txt文本解析并插入MySQL。如果解析一行就插入一次的话,网络会比较耗时。数据量越大越耗时,前段肯定会超时,而且用户体验也不好,我们使用MyBatis Plus批量插入。大概流程如下:

阅读更多