JStorm源码分析小贴士(一)进一步了解 AsyncLoopThread(草稿)
来源:互联网 发布:阿里云备案文件 编辑:程序博客网 时间:2024/06/05 19:56
在 Worker 的源代码中,我们发现有很多地方出现了AsyncLoopThread,下面我们来简单解读一下这个类的源码,并阐述该类的作用。
(一)继承体系
SmartThread 这个接口比较简单,仅仅定义了“灵活线程”所必须实现的方法,如下所示:
public interface SmartThread { public void start(); public void join() throws InterruptedException;; public void interrupt(); public Boolean isSleeping(); public void cleanup();}
(二)主要属性
AsyncLoopThread 包含两个主要成员:
Thread对象
RunnableCallback 对象,RunnableCallback类实现了Java的Runnable接口,所以它的本质是一个可在线程中执行的任务。除此之外,RunnableCallback类还实现了两个自定义接口,分别是Callback和Shutdownable,如下所示:
虽然 RunnableCallback 是一个类,但是它在实现这三个接口时,没有填充任何实际逻辑:
public class RunnableCallback implements Runnable, Callback, Shutdownable { @Override public <T> Object execute(T... args) { return null; } public void preRun() { } @Override public void run() { } public void postRun() { } public Exception error() { return null; } public Object getResult() { return null; } public void shutdown() { } public String getThreadName() { return null; }}
(三)构造方法
AsyncLoopThread 类共有三个构造方法,它们都调用了 init()方法进行构造。
init() 方法接收的参数如下表所示:
参数名
类型
含义
afn
RunnableCallback
需要使用线程异步循环往复执行的任务
daemon
boolean
是否作为守护线程执行,默认值为 false
priority
int
线程的优先级,默认值为 Thread.NORM_PRIORITY
start
boolean
是否立刻启动该线程,默认值为 true
kill_fn
RunnableCallback
指定执行杀死任务的任务,默认值为 AsyncLoopDefaultKill 实例
在 init() 方法中,
private void init(RunnableCallback afn, boolean daemon, RunnableCallback kill_fn, int priority, boolean start) { if (kill_fn == null) { kill_fn = new AsyncLoopDefaultKill(); } Runnable runnable = new AsyncLoopRunnable(afn, kill_fn); thread = new Thread(runnable); String threadName = afn.getThreadName(); if (threadName == null) { threadName = afn.getClass().getSimpleName(); } thread.setName(threadName); thread.setDaemon(daemon); thread.setPriority(priority); thread.setUncaughtExceptionHandler(new UncaughtExceptionHandler() { @Override public void uncaughtException(Thread t, Throwable e) { LOG.error("UncaughtException", e); JStormUtils.halt_process(1, "UncaughtException"); } }); this.afn = afn; if (start) { thread.start(); } }
1. 如果没有指定执行杀死任务的任务,那么默认创建一个 AsyncLoopDefaultKill来执行;
2. 构造一个 AsyncLoopRunnable 对象,它组合了要执行的主任务和负责杀死主任务的任务,作为一个组合任务;
3. 将 AsyncLoopRunnable 对象作为参数,新建一个线程,为其设定名字、是否为守护线程和优先级等基本属性;
4. 若 start 被置为true,那么将立刻启动该线程,执行组合任务。
那么 AsyncLoopRunnable 是如何组合主任务和负责杀死主任务的任务呢?
除了需要组合的两个任务作为成员之外, AsyncLoopRunnable 类中还包含两个原子布尔变量 shutdown 和shutdowned,分别用来记录关闭命令和记录已关闭状态,初始时均为false。使用一个时间戳lastTime记录当前时间。
该类实现了 Java 的Runnable接口,其run()方法实现如下:
@Override public void run() { if (fn == null) { LOG.error("fn==null"); throw new RuntimeException("AsyncLoopRunnable no core function "); } fn.preRun(); try { while (!shutdown.get()) { fn.run(); if (shutdown.get()) { shutdown(); return; } Exception e = fn.error(); if (e != null) { throw e; } Object rtn = fn.getResult(); if (this.needQuit(rtn)) { shutdown(); return; } } } catch (Throwable e) { if (shutdown.get()) { shutdown(); } else { LOG.error("Async loop died!!!" + e.getMessage(), e); killFn.execute(e); } } }
在一个循环体中,
1. 每次循环开始检查 shutdown 标志了解是否接受到停止指令,一旦检测到停止指令为真,立刻退出循环,任务结束;
2. 否则调用主任务的 run() 方法。之后再次检查 shutdown 标志,如果为真,那么执行shutdown()方法,并立刻返回,任务结束;
3. 否则继续执行,看主任务是否异常,如果是,抛出异常,并进行捕获,通过监督线程杀死主任务,任务结束;
4. 一切正常,查看主方法的结果,根据结果判断是否需要终止任务。
needQuit() 方法根据任务的返回值决定是否需要终止任务:
if (rtn != null) { long sleepTime = Long.parseLong(String.valueOf(rtn)); if (sleepTime < 0) { return true; } else if (sleepTime > 0) { long now = System.currentTimeMillis(); long cost = now - lastTime; long sleepMs = sleepTime * 1000 - cost; if (sleepMs > 0) { JStormUtils.sleepMs(sleepMs); lastTime = System.currentTimeMillis(); } else { lastTime = now; } } } return false;
任务的返回值就是需要间隔的时间,如果休眠时间小于0,那么将要终止任务;否则,更新时间戳之后,线程阻塞若干时间后,继续执行。
(四)关键方法
由于实现了 SmartThread 接口,而本身又包含一个 Thread 对象,所以需要实现的方法都是通过Thread对象来实现的,这里不在赘述。
需要注意的是 cleanup() 的实现是调用主任务的 shutdown() 方法:
@Override public void cleanup() { afn.shutdown(); }
(五)综述
从以上分析可以看出,AsyncLoopThread 类封装的是一个每隔一段时间执行一次的主任务,通过后台线程执行,同时设置一个配套的监督任务,用于在主任务发生异常时,中断执行线程。所以该类当做一个通用的简易定时任务类使用。
- JStorm源码分析小贴士(一)进一步了解 AsyncLoopThread(草稿)
- JStorm源码分析(一)Worker核心源码分析(草稿|无代码|无图版)
- JStorm源码分析(二)JStorm中的基本数据结构—— Fields,Values&Tuples(草稿|无图版)
- JStorm源码分析(四)深入解读Task概念与实现(草稿版)
- JStorm与Storm源码分析(一)--nimbus-data
- JStorm与Storm源码分析(一)--nimbus-data
- JStorm源码分析(三)流计算的执行者——SpoutExecutors/BoltExecutors(草稿|无图版)
- MapReduce 的进一步了解(一)
- oschina源码分析:架构篇(草稿)
- oschina源码分析:实现篇(草稿)
- JStorm与Storm源码分析(二)--任务分配,assignment
- JStorm与Storm源码分析(三)--Scheduler,调度器
- JStorm与Storm源码分析(三)--Scheduler,调度器
- JStorm与Storm源码分析(二)--任务分配,assignmen
- jstorm源码分析
- jstorm源码分析: nimbus
- jstorm 源码分析汇总
- jstorm 源码分析: supervisor
- zstu oj 4274 约素(求一个数约数的个数)(暴力法)
- 设计模式——单例模式
- Contest
- Hibernate工作原理及其作用
- 标题:算年龄
- JStorm源码分析小贴士(一)进一步了解 AsyncLoopThread(草稿)
- 趋势引领新发展,电商在线客服系统的未来
- 屏幕获取程序
- pta 天梯地图 (Dijkstra)
- 斐波那契数列的Java表示
- 使用DBWritable完成同mysql交互
- beego_Excel 文件上传
- 退出登陆
- P2P金融借贷项目 前台+后台+数据库源码+移动端后台