一、代码拆解
原始代码
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
这段代码等价于
// 步骤1:创建一个 Runnable 对象
Runnable task = new Runnable() {
@Override
public void run() {
register0(promise);
}
};
// 步骤2:调用 execute 方法,传入这个对象
eventLoop.execute(task);
二、什么是 Runnable?
Runnable 接口定义
public interface Runnable {
void run();
}
Runnable是一个接口- 只有一个方法:
run() - 表示一个可以执行的任务
匿名内部类
new Runnable() {
@Override
public void run() {
register0(promise);
}
}
这是匿名内部类的语法,等价于:
// 定义一个类
class MyTask implements Runnable {
@Override
public void run() {
register0(promise);
}
}
// 创建实例
Runnable task = new MyTask();
三、逐步解析
步骤 1:理解 execute() 方法的参数
// execute 方法的签名
public void execute(Runnable task)
execute()方法需要一个Runnable类型的参数- 这个参数是一个任务,包含了要执行的代码
步骤 2:创建 Runnable 对象
new Runnable() {
@Override
public void run() {
register0(promise);
}
}
这段代码做了什么?
- 创建了一个实现
Runnable接口的匿名类 - 实现了
run()方法 run()方法中的代码是:register0(promise)
步骤 3:传递给 execute()
eventLoop.execute(这个Runnable对象);
- 将创建的
Runnable对象传递给execute()方法 execute()方法会将这个任务添加到队列
四、完整的执行流程
用更简单的例子说明
// 例子1:最简单的形式
eventLoop.execute(new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
});
// 等价于
Runnable task = new Runnable() {
@Override
public void run() {
System.out.println("Hello");
}
};
eventLoop.execute(task);
// 还等价于(使用 Lambda 表达式,Java 8+)
eventLoop.execute(() -> {
System.out.println("Hello");
});
// 或者更简单
eventLoop.execute(() -> System.out.println("Hello"));
回到原始代码
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
这段代码的意思是:
- 创建一个任务(Runnable 对象)
- 这个任务的内容是:调用
register0(promise)方法 - 将这个任务提交给
eventLoop执行
五、详细的执行过程
1. 当前线程(如主线程)执行
// 【主线程】执行到这里
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise); // 这行代码现在不会执行
}
});
// 【主线程】execute() 立即返回,继续执行后面的代码
注意:
register0(promise)这行代码现在不会执行- 它只是被"包装"在
Runnable对象中 - 等待将来被执行
2. execute() 方法内部
// SingleThreadEventExecutor.execute()
public void execute(Runnable task) {
// task 就是那个 Runnable 对象
// task.run() 方法中包含了 register0(promise) 的调用
// 将 task 添加到队列
addTask(task);
// 如果需要,启动线程
if (!inEventLoop()) {
startThread();
}
// 返回
}
3. EventLoop 线程执行任务
// 【EventLoop 线程】在事件循环中
protected void run() {
for (;;) {
// ... select IO 事件 ...
// 执行任务队列中的任务
runAllTasks();
}
}
protected boolean runAllTasks() {
// 从队列中取出任务
Runnable task = taskQueue.poll();
// 执行任务
task.run(); // ← 这里才真正调用 register0(promise)
}
六、用图示说明
代码结构
eventLoop.execute(
┌─────────────────────────────┐
│ new Runnable() { │ ← 创建一个对象
│ @Override │
│ public void run() { │ ← 定义 run() 方法
│ register0(promise); │ ← run() 方法的内容
│ } │
│ } │
└─────────────────────────────┘
);
执行流程
【主线程】
↓
创建 Runnable 对象
↓
┌──────────────────────┐
│ Runnable task = { │
│ run() { │
│ register0(...); │
│ } │
│ } │
└──────────────────────┘
↓
调用 execute(task)
↓
将 task 添加到队列
↓
[taskQueue: task]
↓
execute() 返回
↓
主线程继续执行
【EventLoop 线程】
↓
从队列取出 task
↓
调用 task.run()
↓
执行 register0(promise)
七、类比理解
类比 1:外卖订单
// 你(主线程)下单
外卖平台.接单(new 订单() {
@Override
public void 配送() {
送到你家();
}
});
// 你下完单就可以做其他事了
// 外卖员(EventLoop 线程)接单
订单 order = 从订单队列取出();
order.配送(); // 执行送到你家()
类比 2:待办事项
// 你(主线程)写待办事项
待办清单.添加(new 任务() {
@Override
public void 执行() {
打扫房间();
}
});
// 写完就可以做其他事了
// 将来某个时候(EventLoop 线程)
任务 task = 从待办清单取出();
task.执行(); // 执行打扫房间()
八、为什么要这样写?
问题:为什么不直接调用?
// 为什么不这样写?
register0(promise);
// 而要这样写?
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
答案:线程安全
// 当前线程:主线程
// register0() 必须在 EventLoop 线程中执行
// 如果直接调用
register0(promise); // 在主线程中执行,可能有线程安全问题
// 通过 execute 提交
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise); // 在 EventLoop 线程中执行,线程安全
}
});
九、Lambda 表达式写法(Java 8+)
如果你熟悉 Lambda 表达式,这段代码可以简化为:
// 原始写法
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
// Lambda 写法
eventLoop.execute(() -> register0(promise));
两者完全等价,Lambda 只是更简洁的写法。
十、总结
这段代码做了什么?
eventLoop.execute(new Runnable() {
@Override
public void run() {
register0(promise);
}
});
- 创建一个任务:这个任务是一个
Runnable对象 - 任务的内容:调用
register0(promise)方法 - 提交任务:将任务提交给
eventLoop - 异步执行:任务会在 EventLoop 线程中执行,不是在当前线程
关键点
new Runnable() { ... }是创建一个对象run()方法中的代码是任务的内容execute()是提交任务,不是立即执行- 任务会在将来的某个时刻,在 EventLoop 线程中执行
253



被折叠的 条评论
为什么被折叠?



