NIO Buffer

缓冲区 Buffer 是一个固定容量的数组,其作用是一个作为存储器,或者分段运输区,用于存储和检索数据。

JUC AbstractQueuedSynchronizer

队列同步器 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,而释放锁就是是指线程将状态变量置为了可修改的状态,以便其他线程可以再次尝试修改状态变量

JUC FutureTask

前面整理线程池时说过Executor是执行任务的抽象,而Runnable是任务的抽象。不过,线程池在实际提交任务时,会先将任务包装成一个FutureTask,以实现Future的语义,即异步获取任务结果的能力FutureTask内部实际依赖的是一个Callable,并将任务的执行过程和结果获取委托给它,如果提交的是Runnable,那么也可以通过适配器RunnableAdapter<V>将其适配成一个Callable

java.util.concurrent.Executors
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public static <T> Callable<T> callable(Runnable task, T result) {
if (task == null)
throw new NullPointerException();
return new RunnableAdapter<T>(task, result);
}

static final class RunnableAdapter<T> implements Callable<T> {
final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {
this.task = task;
this.result = result;
}
public T call() {
task.run();
return result;
}
}

相关类图可以如下所示:


JUC ThreadPoolExecutor

Executor是java中任务执行的主要抽象,虽然它是一个简单的接口,但却为灵活而强大的异步任务执行框架提供了基础,它提供了一种标准的方法将任务的提交过程与执行过程解耦开来。

java.util.concurrent.Executor
1
2
3
public interface Executor{
void excute(Runnable command);
}