Java学习笔记之J.U.C和Java的IO机制篇

简介

J.U.C全称为java.util.concurrent,是java解决高并发的一种方案其中包含CAS(Compare and Swap)和AQS(AbstractQueuedSynchronizer)的概念。

  • CAS是atomic包的基础;
  • AQS是locks包和一些常用类如:Semophore、ReentrantLock等类的基础。

J.U.C包的分类

Java学习笔记之J.U.C和Java的IO机制篇

并发工具类
Java学习笔记之J.U.C和Java的IO机制篇
CountDownLatch:让主线程等待一组事件发生后继续执行。
  事件:CountDownLatch里的countDown()方法。

CyclicBarrier:阻塞当前线程,等待其他线程。

  • 等待其它线程,且会阻塞当前线程,所有线程必须同时到达栅栏位置后,才能继续执行;
  • 所有线程到达栅栏处,可以触发执行另一个预先设置的线程。

Semaphore:控制某个资源可被同时访问的线程个数。

Exchanger:两个线程到达同步点,相互交换数据。

BlockingQueue:提供可阻塞的入队和出队操作(主要用于生产者-消费者模式,队尾添加,队头消费)

1. ArrayBlockingQueue : —个由数组结构组成的有界阻塞队列;
2. LinkedBlockingQueue : —个由链表结构组成的有界/无界阻塞队列;
3. PriorityBlockingQueue :—个支持优先级排序的无界阻塞队列;

4. DealyQueue :—个使用优先级队列实现的无界阻塞队列;
5. SynchronousQueue :—个不存储元素的阻塞队列;
6. LinkedTransferQueue :—个由链表结构组成的无界阻塞队列;
7. LinkedBlockingDeque : —个由链表结构组成的双向阻塞队列。

Java的IO机制

Java的IO机制包括BIO、NIO、AIO,下面我们来看看它们的内部逻辑。

Block-IO:inputStream和OutputStream、Reader和Writer。
Java学习笔记之J.U.C和Java的IO机制篇
NonBlock-IO:构建多路复用、同步非阻塞的IO操作
Java学习笔记之J.U.C和Java的IO机制篇
Asynchronous IO:基于事件和回调机制
Java学习笔记之J.U.C和Java的IO机制篇
AIO如何进一步加工处理结果?

  • 基于回调:实现CompletionHandler接口,调用时触发回调函数;
  • 返回Future:通过isDone()查看是否准备好,通过get()等待返回数据。

IO多路复用:调用系统级别的select/poll/epoll
Java学习笔记之J.U.C和Java的IO机制篇
select、poll、epoll 区别
1、支持一个进程所能打开的最大连接数

select 单个进程所能打开的最大连接数有FD_SETSIZE宏定义,其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_SETSIZE为3264),当然我们可以对进行修改,然后重新编译内核,但是性能可能会受到影响,这需要进一步的测试。
poll poll本质上和select没有区别,但是它没有最大连接数的限制,原因是它是基于链表来存储的。
epoll 虽然连接数有上限,但是很大,1G内存的机器上可以打开10万左右的连接。

2、FD(FileDescriptor)剧增后带来的IO效率问题

select 因为每次调用时都会对连接进行线性遍历,所以随着FD的增加会造成遍历速度慢,线性下降性能问题。
poll 同上
epoll 因为epoll内核中实现是根据每个fd上的callback函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll没有前面两者的线性下降的性能问题,但是所有socket都很活跃的情况下,可能会有性能问题。

3、 消息传递方式

select 内核需要将消息传递到用户空间,都需要内核拷贝动作(4次左右)
poll 同上
epoll epoll通过内核和用户空间共享一块内存来实现的。

BIO、NIO、AIO区别

属性/模型 阻塞BIO 非阻塞NIO 异步AIO
blocking 阻塞并同步 非阻塞但同步 非阻塞并异步
线程数(服务端:客户端) 1:1 1:N 0:N
复杂度 简单 较复杂 复杂
吞吐量