NIO Buffer
缓冲区 Buffer 是一个固定容量的数组,其作用是一个作为存储器,或者分段运输区,用于存储和检索数据。
缓冲区 Buffer 是一个固定容量的数组,其作用是一个作为存储器,或者分段运输区,用于存储和检索数据。
这里整理需要涉及一些C++源码,待后续进行梳理
队列同步器 AbstractQueuedSynchronizer(AQS),是用来构建锁或者其他同步组件的基础框架。它使用一个int变量来表示同步状态,通过CAS操作对同步状态进行修改,确保状态的改变是安全的。通过内置的FIFO(First In First Out)队列来完成资源获取线程的排队工作。
AQS同步与synchronized同步是采用的两种不同的机制:
synchronized在编译后,会在同步块的前后分别添加monitorenter和monitorexit两个字节码指令,这两个指令需要关联一个监视对象,当线程执行monitorenter指令时,需要首先获得获得监视对象的锁,即进入同步块的凭证,才能进入同步块,当线程离开同步块时,执行monitorexit指令,释放对象锁。
AQS同步中,使用一个int类型的变量state来表示当前同步块的状态。以独占式同步为例,state的有效值为0和1,其中0表示当前同步块中没有线程,1表示同步块中已经有线程在执行。当线程要进入同步块时,需要首先判断state的值是否为0,假设为0,会尝试将state修改为1,只有修改成功了之后,线程才可以进入同步块,并通过CAS操作确保同一时刻只有一个线程操作成功。当线程离开同步块时,会修改state的值为0,并唤醒等待的线程。所以在AQS同步中,线程获得锁实际上是指线程成功修改了状态变量state,而释放锁就是是指线程将状态变量置为了可修改的状态,以便其他线程可以再次尝试修改状态变量
前面整理线程池时说过Executor
是执行任务的抽象,而Runnable
是任务的抽象。不过,线程池在实际提交任务时,会先将任务包装成一个FutureTask
,以实现Future
的语义,即异步获取任务结果的能力。FutureTask
内部实际依赖的是一个Callable
,并将任务的执行过程和结果获取委托给它,如果提交的是Runnable
,那么也可以通过适配器RunnableAdapter<V>
将其适配成一个Callable
1 | public static <T> Callable<T> callable(Runnable task, T result) { |
相关类图可以如下所示:
Executor
是java中任务执行的主要抽象,虽然它是一个简单的接口,但却为灵活而强大的异步任务执行框架提供了基础,它提供了一种标准的方法将任务的提交过程与执行过程解耦开来。
1 | public interface Executor{ |