Vert.x 源码解析(4.x)(一)——Context源码解析

目录

在这里插入图片描述

1.简介

Vert.x 中,多线程环境下的资源管理和状态维护是一个复杂的问题。为了解决这个问题,Vert.x 引入了 Context 这个核心概念。Context 负责在多线程环境下协调异步操作,提供线程安全的资源访问,并确保异步操作的正确执行顺序。本文将对 Vert.x 的 Context 进行源码解析,探讨它在异步编程中的作用、设计原理以及关键的实现细节。

在这里插入图片描述

2 源代码解析

2.1 Handler

此方法就是一个接口,通过实现该接口,做为回调使用

@FunctionalInterface
public interface Handler<E> {

  /**
   * Something has happened, so handle it.
   *
   * @param event  the event to handle
   */
  void handle(E event);
}

2.2 Context

Context接口,在此方法内部定义了基本的事件处理,比如立即执行任务,阻塞线程执行任务等。

public interface Context {
  /**
   * 当前线程是否在work线程
   */
  static boolean isOnWorkerThread() {
    Thread t = Thread.currentThread();
    return t instanceof VertxThread && ((VertxThread) t).isWorker();
  }
  /**
   * 当前线程是否在eventloop线程
   */
  static boolean isOnEventLoopThread() {
    Thread t = Thread.currentThread();
    return t instanceof VertxThread && !((VertxThread) t).isWorker();
  }
  /**
   * 当前线程是否是vertx线程
   */
  static boolean isOnVertxThread() {
    return Thread.currentThread() instanceof VertxThread;
  }
  /**
   * 当前线程立马运行handler任务,最后调用的也是dispatch
   */
  void runOnContext(Handler<Void> action);
  /**
   * work线程上运行,运行耗时任务,默认如果超出十秒则会写入日志。最后调用的也是dispatch
   * @param blockingCodeHandler 执行逻辑
   * @param ordered 如果为true则进入队列,这样子会串行执行,如果为false则立马执行这样子是并发执行
   * @param <T>
   * @return
   */
  <T> Future<@Nullable T> executeBlocking(Handler<Promise<T>> blockingCodeHandler, boolean ordered);
   /**
   * 是否是eventloopContext
   */   
  boolean isEventLoopContext(); 
  /**
   * 是否是workContext
   */    
  boolean isWorkerContext();
  //get put  是context内部的一个ConcurrentHashMap,用于存储值,其实还有localdatade的get,put方法
  <T> T get(Object key);
  void put(Object key, Object value);
  //部署id 
  String deploymentID();
    
}

2.3 ContextInternal

ContextInternal是Context接口的一个扩展,它增加了一些内部使用的方法和功能。它通常不直接暴露给应用程序开发者,比如内部获取当前线程的Context。

dispatch中beginDispatch和endDispatch是一个很重要的方法,如果是Vertx的线程他是让当前线程所绑定的Context先切换当下的Context,接着在end里面重新切换回去。如果不是Vertx的线程就用ThreadLocal进行切换当前Context,在end中切换回去

public interface ContextInternal extends Context {
    
   //获取当前线程Context,所以原则上每个线程只有一个Context
  static ContextInternal current() {
    Thread thread = Thread.currentThread();
    //如果是Vertx的线程,则直接获取,因为每个Vertx线程创建的时候会绑定Context
    if (thread instanceof VertxThread) {
      return ((VertxThread) thread).context();
    } else {
      //如果不是Vert的线程则从ThreadLocal里进行获取
      VertxImpl.ContextDispatch current = VertxImpl.nonVertxContextDispatch.get();
      if (current != null) {
        return current.context;
      }
    }
    return null;
  }        
  /**
   * 里面包含线程池,包括对线程池进行监测性能的PoolMetrics
   * @return the context worker pool
   */
  WorkerPool workerPool();
  @Override
  /**
   * 通过执行器立马执行任务,参数就是Handler
   * @param action  the action to run
   */
  @Override
  default void runOnContext(Handler<Void> action) {
    executor().execute(() -> dispatch(action));
  }
  default void dispatch(Handler<Void> handler) {
    dispatch(null, handler);
  }
  //你看dispatch其实就是执行传入进来的Handler类的handle方法
  //这个方法很重要的方法就是讲线程绑定的context做切换
  default <E> void dispatch(E event, Handler<E> handler) {
    //beginDispatch,endDispatch主要是调用Vertx的方法执行,
    //context做切换以及比如一些执行时间统计、类加载器绑定等
    ContextInternal prev = beginDispatch();
    try {
      //重点执行handle
      handler.handle(event);
    } catch (Throwable t) {
      reportException(t);
    } finally {
      endDispatch(prev);
    }
  }
    /**
   * 切换当前的上下文Context
   */  
  default ContextInternal beginDispatch() {
    VertxImpl vertx = (VertxImpl) owner();
    return vertx.beginDispatch(this);
  }

  /**
   * 重新切换原先的上下文Context
   */
  default void endDispatch(ContextInternal previous) {
    VertxImpl vertx = (VertxImpl) owner();
    vertx.endDispatch(previous);
  }  
  
}

vertx.beginDispatch

该方法是Vertx的实现类VertxImpl里的。

具体就是先获取原先该线程或者ThreadLocal有无绑定的Context,有的话把这个context保留下来赋值给prev,并且把传入进来的context与当前线程和ThreadLocal绑定

//存储Context的类
static final ThreadLocal<ContextDispatch> nonVertxContextDispatch = new ThreadLocal<>(); 
//内部包含context以及classLoader
static class ContextDispatch {
    ContextInternal context;
    ClassLoader topLevelTCCL;
}

ContextInternal beginDispatch(ContextInternal context) {
    //获取当前线程
    Thread thread = Thread.currentThread();
    ContextInternal prev;
    //判断是否是VertxThread
    if (thread instanceof VertxThread) {
      //如果是则直接根据VertxThread里获取Context
      VertxThread vertxThread = (VertxThread) thread;
      prev = vertxThread.context;
      //执行时间统计
      if (!ContextBase.DISABLE_TIMINGS) {
        vertxThread.executeStart();
      }
      //将线程context改成传入进来的context
      vertxThread.context = context;
      if (!disableTCCL) {
        if (prev == null) {
          vertxThread.topLevelTCCL = Thread.currentThread().getContextClassLoader();
        }
        if (context != null) {
          thread.setContextClassLoader(context.classLoader());
        }
      }
    } else {
      //如果不是则执行该方法
      prev = beginDispatch2(thread, context);
    }
    //最后返回原先的Context(这里保留原先的context主要是后面之行结束了,线程的context要切换回去)
    return prev;
  }
-----------------------beginDispatch2-------------------方法
  private ContextInternal beginDispatch2(Thread thread, ContextInternal context) {
    //从ThreadLocal里进行获取ContextDispatch,内部就是Context以及classload
    ContextDispatch current = nonVertxContextDispatch.get();
    ContextInternal prev;
    //如果当前的不为空,则将prev设置成当前的context
    if (current != null) {
      prev = current.context;
    } else {
      //如果为空,则重新new一个设置会null并且在thradlocal里存储
      current = new ContextDispatch();
      nonVertxContextDispatch.set(current);
      prev = null;
    }
    //将传入的context赋值给当前线程context
    current.context = context;
    if (!disableTCCL) {
      if (prev == null) {
        current.topLevelTCCL = Thread.currentThread().getContextClassLoader();
      }
      thread.setContextClassLoader(context.classLoader());
    }
    //返回原先(当前)的context
    return prev;
  }

vertx.endDispatch

这里就是将startDispatch返回的原始绑定的Context传入进来进行切换。

void endDispatch(ContextInternal prev) {
  //获取当前线程,prev是刚刚startDispathc返回的值传进来的
  Thread thread = Thread.currentThread();
  if (thread instanceof VertxThread) {
    VertxThread vertxThread = (VertxThread) thread;
    //将当前线程的context切换回原来的
    vertxThread.context = prev;
    if (!disableTCCL) {
      ClassLoader tccl;
      if (prev == null) {
        tccl = vertxThread.topLevelTCCL;
        vertxThread.topLevelTCCL = null;
      } else {
        tccl = prev.classLoader();
      }
      Thread.currentThread().setContextClassLoader(tccl);
    }
    //这边就是结束时间
    if (!ContextBase.DISABLE_TIMINGS) {
      vertxThread.executeEnd();
    }
  } else {
    endDispatch2(prev);
  }
}

private void endDispatch2(ContextInternal prev) {
  ClassLoader tccl;
  //这边也是同理将原先的prev绑定重新给到threadLocal,如果为空则直接remove
  ContextDispatch current = nonVertxContextDispatch.get();
  if (prev != null) {
    current.context = prev;
    tccl = prev.classLoader();
  } else {
    nonVertxContextDispatch.remove();
    tccl = current.topLevelTCCL;
  }
  if (!disableTCCL) {
    Thread.currentThread().setContextClassLoader(tccl);
  }
}

2.4 ContextBase

2.4.1 ContextBase代码

是ContextInternal的实现类,它包含具体功能的实现,比如执行耗时任务,

public abstract class ContextBase implements ContextInternal {
  //数据存储
  private ConcurrentMap<Object, Object> data;
  //本地数据存储
  private ConcurrentMap<Object, Object> localData;
  //内部任务队列
  final TaskQueue internalOrderedTasks;
  //内部任务线程池
  final WorkerPool internalWorkerPool;
  //工作线程池,外部调用
  final WorkerPool workerPool;
  //任务队列
  final TaskQueue orderedTasks; 
  //eventloop线程
  private final EventLoop eventLoop;
 ........
     
  /**
   *
   * @param vertx
   * @param eventLoop  它从eventGroup里进行取出来的,用于处理事件
   * @param internalWorkerPool 可能会造成阻塞的内部任务执行器
   * @param workerPool  工作现场执行器,用于普通的异步任务
   * @param deployment  用于管理当前Verticle的部署和卸载
   * @param closeFuture 关闭的future
   * @param tccl  当前线程的classLoader
   */
  protected ContextBase(VertxInternal vertx,
                        EventLoop eventLoop,
                        WorkerPool internalWorkerPool,
                        WorkerPool workerPool,
                        Deployment deployment,
                        CloseFuture closeFuture,
                        ClassLoader tccl) {
    this.deployment = deployment;
    this.config = deployment != null ? deployment.config() : new JsonObject();
    this.eventLoop = eventLoop;
    this.tccl = tccl;
    this.owner = vertx;
    this.workerPool = workerPool;
    this.closeFuture = closeFuture;
    this.internalWorkerPool = internalWorkerPool;
    //有序任务队列,内部都是用的LinkedList,目的肯定是有序
    this.orderedTasks = new TaskQueue();
    //用于阻塞的任务队列
    this.internalOrderedTasks = new TaskQueue();
  }     
  //-------------------executeBlocking系列--------------------------------------------
  @Override
  public <T> Future<T> executeBlockingInternal(Handler<Promise<T>> action) {
    return executeBlocking(this, action, internalWorkerPool, internalOrderedTasks);
  }
  @Override
  public <T> Future<T> executeBlockingInternal(Handler<Promise<T>> action, boolean ordered) {
    return executeBlocking(this, action, internalWorkerPool, ordered ? internalOrderedTasks : null);
  }

  @Override
  public <T> Future<T> executeBlocking(Handler<Promise<T>> blockingCodeHandler, boolean ordered) {
    return executeBlocking(this, blockingCodeHandler, workerPool, ordered ? orderedTasks : null);
  }
  @Override
  public <T> Future<T> executeBlocking(Handler<Promise<T>> blockingCodeHandler, TaskQueue queue) {
    return executeBlocking(this, blockingCodeHandler, workerPool, queue);
  }
    
 /**
   * 上面的方法最后还是调用该方法
   * @param context contex上下文就是本身
   * @param blockingCodeHandler 就是传入进来的Handler(实际需要执行的任务)
   * @param workerPool 内部包含线程池以及性能检测指标类
   * @param queue 队列,根据是否有队列来判断是顺序执行还是并发执行
   * @param <T>
   * @return
   */
  static <T> Future<T> executeBlocking(ContextInternal context, Handler<Promise<T>> blockingCodeHandler,
      WorkerPool workerPool, TaskQueue queue) {
    //是个接口,根据实现它的begin、rejected、end内写入监测代码,后文给你展示下
    PoolMetrics metrics = workerPool.metrics();
    Object queueMetric = metrics != null ? metrics.submitted() : null;
    //获取Promise,就是我们前面ContextInternal的方法
    Promise<T> promise = context.promise();
    Future<T> fut = promise.future();
    try {
      //创建Runnable
      Runnable command = () -> {
        Object execMetric = null;
        //这边就是当他不为空时会调用监测类的begin方法
        if (metrics != null) {
          execMetric = metrics.begin(queueMetric);
        }
        //这个方法就是ContextInternal内实现的方法,就是调用handle.handle,这里重新创建了一个Handler,并且把传入进来的Handler写在它的实现方法里
        context.dispatch(promise, f -> {
          try {
            //传递了promise,promise是用来告知结果的
            blockingCodeHandler.handle(promise);
          } catch (Throwable e) {
            promise.tryFail(e);
          }
        });
        //这里也是监测类的end方法
        if (metrics != null) {
          metrics.end(execMetric, fut.succeeded());
        }
      };
      //这里获取workerPool的线程池
      Executor exec = workerPool.executor();
      //如果队列没有则直接线程池执行,如果有则提交给队列执行
      if (queue != null) {
        queue.execute(command, exec);
      } else {
        exec.execute(command);
      }
    } catch (RejectedExecutionException e) {
      // 任务异常监测调用
      if (metrics != null) {
        metrics.rejected(queueMetric);
      }
      throw e;
    }
    //这里返回future
    return fut;
  }
    //-------------------execute,runOnContext,emit--------------------------------------------
    //exceute以及runOnContext,emit实际执行方法都交由子类进行执行
  @Override
  public void execute(Runnable task) {
    execute(this, task);
  }
  
  protected abstract <T> void execute(ContextInternal ctx, Runnable task);

  @Override
  public final <T> void execute(T argument, Handler<T> task) {
    execute(this, argument, task);
  }

  protected abstract <T> void execute(ContextInternal ctx, T argument, Handler<T> task);

  @Override
  public <T> void emit(T argument, Handler<T> task) {
    emit(this, argument, task);
  }

  protected abstract <T> void emit(ContextInternal ctx, T argument, Handler<T> task);
    
}

2.4.2 TaskQueue

内部定义了一个LinkedList来存储任务,接着按照LinkedList添加顺序来顺序执行任务,因为代码量比较少,我全部添加进来并且加了注释。

public class TaskQueue {

  static final Logger log = LoggerFactory.getLogger(TaskQueue.class);

  private static class Task {

    private final Runnable runnable;
    private final Executor exec;

    public Task(Runnable runnable, Executor exec) {
      this.runnable = runnable;
      this.exec = exec;
    }
  }

  // @protectedby tasks
  private final LinkedList<Task> tasks = new LinkedList<>();

  // @protectedby tasks
  private Executor current;

  private final Runnable runner;

  //在开始就进行初始化了runner执行的就是run方法
  public TaskQueue() {
    runner = this::run;
  }
  /**
   * Run a task.
   *
   * @param task the task to run.
   */
  public void execute(Runnable task, Executor executor) {
    //同步,防止多线程添加,这样子能保证顺序
    synchronized (tasks) {
      //将任务添加进去
      tasks.add(new Task(task, executor));
      //判断当前线程池是否为空,为空则赋值,并且通过executor执行runner,实际执行的就是下面那个run方法
      if (current == null) {
        current = executor;
        try {
          executor.execute(runner);
        } catch (RejectedExecutionException e) {
          current = null;
          throw e;
        }
      }
    }
  }
  //实际执行的就是这一段,把task里的任务获取进行执行,没有任务则退出,不然就死循环执行
  private void run() {
    for (; ; ) {
      final Task task;
      //加锁,保证任务队列的操作是线程安全的
      synchronized (tasks) {
        task = tasks.poll();
        //没有任务直接退出死循环
        if (task == null) {
          current = null;
          return;
        }
        //如果task的线程与当前线程不是同一个线程
        if (task.exec != current) {
          //不是则将任务重新添加进tasks
          tasks.addFirst(task);
          //并且重新执行run方法
          task.exec.execute(runner);
          //设置当前current位当前的线程
          current = task.exec;
          return;
        }
      }
      try {
        //是当前线程直接执行
        task.runnable.run();
      } catch (Throwable t) {
        log.error("Caught unexpected Throwable", t);
      }
    }
  };


}

2.4.3 PoolMetrics

可以根据实现PoolMetrics在其begin、rejected、end内写入监测代码

public interface PoolMetrics<T> extends Metrics {

  /**
   * 任务提交
   */
  default T submitted() {
    return null;
  }

  /**
   * 任务开始
   * The submitted task start to use the resource.
   *
   */
  default T begin(T t) {
    return null;
  }

  /**
   * 记录任务被拒绝执行
   */
  default void rejected(T t) {
  }

  /**
   * 任务结束
   */
  default void end(T t, boolean succeeded) {
  }

}

2.5 WorkerContext

public class WorkerContext extends ContextBase {
  WorkerContext(VertxInternal vertx,
                WorkerPool internalBlockingPool,
                WorkerPool workerPool,
                Deployment deployment,
                CloseFuture closeFuture,
                ClassLoader tccl) {
    super(vertx, vertx.getEventLoopGroup().next(), internalBlockingPool, workerPool, deployment, closeFuture, tccl);
  }
 
  //----------------------runOnContext实际实现-----------------------------  
  @Override
  protected void runOnContext(ContextInternal ctx, Handler<Void> action) {
    try {
      run(ctx, null, action);
    } catch (RejectedExecutionException ignore) {
      // Pool is already shut down
    }
  }
  private <T> void run(ContextInternal ctx, T value, Handler<T> task) {
    Objects.requireNonNull(task, "Task handler must not be null");
     //调用executor(),以及newRunaable,内部就是ContextInternal的ctx.dispatch(value, task)方法
    executor().execute(() -> ctx.dispatch(value, task));
  }
  /**
   * 看代码实际上也是加入到orderedTasks队列进行执行
   * @return
   */    
  @Override
  public Executor executor() {
    if (executor == null) {
      executor = command -> {
        PoolMetrics metrics = workerPool.metrics();
        Object queueMetric = metrics != null ? metrics.submitted() : null;
        //加入到队列
        orderedTasks.execute(() -> {
          Object execMetric = null;
          if (metrics != null) {
            execMetric = metrics.begin(queueMetric);
          }
          try {
            command.run();
          } finally {
            if (metrics != null) {
              metrics.end(execMetric, true);
            }
          }
        }, workerPool.executor());
      };
    }
    return executor;
  }    
 //---------------------------execute和emit实际实现----------------------------
 //execute和emit实现的都是调用execute(orderedTasks, argument, task)方法,无非就是一个通过外部Handler,一个内部又new Handler了一个把传入进来的  //Handler给了ContextInternal的ctx.dispatch(value, task)方法执行
  @Override
  protected <T> void execute(ContextInternal ctx, T argument, Handler<T> task) {
    execute(orderedTasks, argument, task);
  }

  @Override
  protected <T> void emit(ContextInternal ctx, T argument, Handler<T> task) {
    execute(orderedTasks, argument, arg -> {
      ctx.dispatch(arg, task);
    });
  }
    
  /**
   * 执行任务
   * @param queue 队列
   * @param argument 执行返回值
   * @param task task handler
   * @param <T>
   */
  private <T> void execute(TaskQueue queue, T argument, Handler<T> task) {
     //判断当前调用线程是否work线程,是的话则直接执行,不是的话进入队列执行
    if (Context.isOnWorkerThread()) {
      task.handle(argument);
    } else {
      PoolMetrics metrics = workerPool.metrics();
      Object queueMetric = metrics != null ? metrics.submitted() : null;
      //进入队列执行
      queue.execute(() -> {
        Object execMetric = null;
        if (metrics != null) {
          execMetric = metrics.begin(queueMetric);
        }
        try {
          task.handle(argument);
        } finally {
          if (metrics != null) {
            metrics.end(execMetric, true);
          }
        }
      }, workerPool.executor());
    }
  }    
}

2.5.2 总结

**execute(): **

1.如果当前线程是work线程则直接执行。

2.如果不是则进入orderedTasks队列顺序执行,并且在执行前面添加了PoolMetrics的监测方法。

3.但是都带有返回值

runOnContext:

进入orderedTasks队列顺序执行,用的workerpool,并且在执行前面添加了PoolMetrics的监测方法

emit:

1.如果当前线程是work线程则直接执行。

2.如果不是则进入orderedTasks队列顺序执行,并且在执行前面添加了PoolMetrics的监测方法。

3.但是都带有返回值

4.唯一与execute不同的是它重新创建了一个handler,把传入进来的handler给了ContextInternal.dispatch执行

2.6 EventLoopContext

2.6.1 代码分析

public class EventLoopContext extends ContextBase {
  //都是调用的父类,所以注释写在父类里面
  EventLoopContext(VertxInternal vertx,
                   EventLoop eventLoop,
                   WorkerPool internalBlockingPool,
                   WorkerPool workerPool,
                   Deployment deployment,
                   CloseFuture closeFuture,
                   ClassLoader tccl) {
    super(vertx, eventLoop, internalBlockingPool, workerPool, deployment, closeFuture, tccl);
  }
 //----------------------runOnContext实际实现-----------------------------    
  /**
   * 直接EventLoop直接执行
   * @param ctx
   * @param action
   */
  @Override
  protected void runOnContext(ContextInternal ctx, Handler<Void> action) {
    try {
      nettyEventLoop().execute(() -> ctx.dispatch(action));
    } catch (RejectedExecutionException ignore) {
      // Pool is already shut down
    }
  }
  public EventLoop nettyEventLoop() {
    return eventLoop;
  }
 //---------------------------execute和emit实际实现----------------------------  
/**
   * 直接在eventloop里面进行执行
   * @param ctx
   * @param argument
   * @param task
   * @param <T>
   */
  @Override
  protected <T> void emit(ContextInternal ctx, T argument, Handler<T> task) {
    EventLoop eventLoop = nettyEventLoop();
    //如果是eventloop直接执行
    if (eventLoop.inEventLoop()) {
      ContextInternal prev = ctx.beginDispatch();
      try {
        task.handle(argument);
      } catch (Throwable t) {
        reportException(t);
      } finally {
        ctx.endDispatch(prev);
      }
    } else {
      //如果不是则直接调用eventloop线程执行
      eventLoop.execute(() -> emit(ctx, argument, task));
    }
  }

  /**
   * 还是在eventloop内部执行
   * <ul>
   *   <li>When the current thread is event-loop thread of this context the implementation will execute the {@code task} directly</li>
   *   <li>Otherwise the task will be scheduled on the event-loop thread for execution</li>
   * </ul>
   */
  @Override
  protected <T> void execute(ContextInternal ctx, T argument, Handler<T> task) {
    EventLoop eventLoop = nettyEventLoop();
    if (eventLoop.inEventLoop()) {
      task.handle(argument);
    } else {
      eventLoop.execute(() -> task.handle(argument));
    }
  }

  /**
   * 还是在eventloop内部执行
   * @param ctx
   * @param task
   * @param <T>
   */
  @Override
  protected <T> void execute(ContextInternal ctx, Runnable task) {
    EventLoop eventLoop = nettyEventLoop();
    if (eventLoop.inEventLoop()) {
      task.run();
    } else {
      eventLoop.execute(task);
    }
  }
}

2.6.2 总结

execute(): 进入EventLoop线程直接执行

runOnContext:直接也是进入EventLoop线程调用ContextInternal.dispatch执行

emit:使用EventLoop线程执行,自己加上了beginDispatch和end方法,实际是和ContextInternal的dispatch内部方法是一样的

2.7 总结

主要总结:

ContextBase内部默认实现了executeBlocking和executeBlockingInternal方法,用这个来执行队列任务。

EventLoopContext则是全部由EventLoop线程来进行执行

WorkerContext则主要是通过线程池进队列执行。

3. 使用方式

3.1 创建

那么它是在哪里使用的呢,它其实贯穿Vertx的始末,只要由任务执行,线程相关都有它。接下来我举例子。

首先它是在VertImpl里进行创建的

比如创建EventLoopContext的创建和WorkContext的创建

@Override
public EventLoopContext createEventLoopContext(Deployment deployment, CloseFuture closeFuture, WorkerPool workerPool, ClassLoader tccl) {
  return new EventLoopContext(this, eventLoopGroup.next(), internalWorkerPool, workerPool != null ? workerPool : this.workerPool, deployment, closeFuture, disableTCCL ? null : tccl);
}

@Override
public EventLoopContext createEventLoopContext(EventLoop eventLoop, WorkerPool workerPool, ClassLoader tccl) {
  return new EventLoopContext(this, eventLoop, internalWorkerPool, workerPool != null ? workerPool : this.workerPool, null, closeFuture, disableTCCL ? tccl : null);
}

@Override
public EventLoopContext createEventLoopContext() {
  return createEventLoopContext(null, closeFuture, null, Thread.currentThread().getContextClassLoader());
}

@Override
public WorkerContext createWorkerContext(Deployment deployment, CloseFuture closeFuture, WorkerPool workerPool, ClassLoader tccl) {
  return new WorkerContext(this, internalWorkerPool, workerPool != null ? workerPool : this.workerPool, deployment, closeFuture, disableTCCL ? null : tccl);
}

@Override
public WorkerContext createWorkerContext() {
  return createWorkerContext(null, closeFuture, null, Thread.currentThread().getContextClassLoader());
}

那么在哪里调用呢

3.2 调用获取

VertxImpl

先获取再调用

//比如先获取后创建
public ContextInternal getOrCreateContext() {
  ContextInternal ctx = getContext();
  if (ctx == null) {
    // We are running embedded - Create a context
    //如果为空则进行创建并且加入到stickyContext里面
    ctx = createEventLoopContext();
    stickyContext.set(new WeakReference<>(ctx));
  }
  return ctx;
}

DeploymentManager的doDeploy方法

就是再Vert.x调用deployVerticle进行部署的时候会调用

ContextBase context = (options.isWorker() ? vertx.createWorkerContext(deployment, closeFuture, workerPool, tccl) :

3.3 使用

使用的地方太多了,包括NetServer,NetClient等等等等,它内部的EventLoop就是用于Netty的客户端服务端收发信息所用,后续将Netserve和NetClient等会详细说明

4 额外说明

Context和线程其实没有强关联关系。

当部署的时候会创建一个新的Context。

当不是部署的时候获取Context会首先获取Thread以及ThreadLocal里的Context,如果没有的话则会创建一个EventLoopContext并且添加到ThreadLocal。但是这是会更改的,当当前的线程通过其他Context执行任务的时候就会将当前线程的Context进行替换,直到执行完任务才会将Context替换回去

问题

为什么要先介绍Context呢?

因为Vertx的Context贯穿始末,包括Server,部署,EventBus等等等等,都是会用到的,因为它负责管理线程,异步任务执行。

源码注释版本

我目前在源码上都加注释,后续如果有需要可以找我拿加了代码注释的Vert.x源码

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值