擴(kuò)展異步并行調(diào)度框架asyncLoad支持注解配置

異步并行加載框架

一父泳、 需求

隨著業(yè)務(wù)越來(lái)越復(fù)雜澈吨,對(duì)應(yīng)的代碼也越來(lái)越復(fù)雜,耗時(shí)也越來(lái)越多纲熏,因此急需一套并行框架妆丘,通過(guò)搜索發(fā)現(xiàn)阿里提供了一個(gè)并行框架asyncLoad(https://github.com/alibaba/asyncload.git),但是此框架不支持注解的方式局劲,使的對(duì)應(yīng)的代碼侵入性很大勺拣,所以對(duì)asyncLoad框架進(jìn)行擴(kuò)展,使其能夠支持對(duì)應(yīng)的注解配置的方式來(lái)進(jìn)行異步并行鱼填。</pre>

二药有、 實(shí)現(xiàn)原理

1. 異步并行基本實(shí)現(xiàn)方式:
  • 原理:基本就是線程池 + Future 的結(jié)合來(lái)實(shí)現(xiàn);
  • 優(yōu)點(diǎn):開(kāi)發(fā)靈活
  • 缺點(diǎn):需要開(kāi)發(fā)人員了解整個(gè)并行框架苹丸,且對(duì)代碼有侵入愤惰,而且對(duì)應(yīng)的返回結(jié)果是Future<對(duì)象> 和本身原來(lái)的返回結(jié)果<對(duì)象> 不一樣,那么在寫(xiě)代碼的時(shí)候就要考慮這些差異赘理;

為了解決異步并行基本實(shí)現(xiàn)方式的缺點(diǎn)宦言,就是不需要開(kāi)發(fā)人員為了實(shí)現(xiàn)異步并行使原來(lái)代碼實(shí)現(xiàn)的方式要進(jìn)行改變,因此需要另外一種異步并行更通用的實(shí)現(xiàn)方式商模,如asyncLoad這種;

2. 異步并行通用實(shí)現(xiàn)方式:
  • 原理:線程池 + Future + Cglib 結(jié)合的方式來(lái)實(shí)現(xiàn)
  • 優(yōu)點(diǎn):正好是異步并行基本實(shí)現(xiàn)方式對(duì)應(yīng)的缺點(diǎn)奠旺,不需要基礎(chǔ)開(kāi)發(fā)人員了解更多異步并行實(shí)現(xiàn)方式,可以讓基礎(chǔ)開(kāi)發(fā)人員還是按照原來(lái)開(kāi)發(fā)串行執(zhí)行代碼一樣進(jìn)行開(kāi)發(fā)施流,唯一的不同就是在需要異步并行執(zhí)行的方法上增加對(duì)應(yīng)的配置(xml响疚,注解等方式);
  • 缺點(diǎn):cglib本身的方式帶來(lái)的缺點(diǎn)(通過(guò)實(shí)現(xiàn)對(duì)應(yīng)目標(biāo)類的子類來(lái)實(shí)現(xiàn)動(dòng)態(tài)代理,并且可以在生成子類的時(shí)候在對(duì)應(yīng)方法上進(jìn)行攔截瞪醋,增強(qiáng)子類方法的功能)忿晕,但是這種方式的代理本身不支持final類(因?yàn)閒inal類不支持生成對(duì)應(yīng)的子類),因此對(duì)應(yīng)的像基元類型就不支持银受;靈活性不如基礎(chǔ)的好践盼;

三、 增加注解配置

1. 設(shè)計(jì)

Asyncload原先整體設(shè)計(jì)對(duì)應(yīng)的類圖如下:


asyncload類圖.jpg

AsyncLoad 注解對(duì)應(yīng)的類圖如下:


擴(kuò)展asyncLoad支持注解對(duì)應(yīng)的類圖

2. 實(shí)現(xiàn)

2.1類功能簡(jiǎn)介

  • 注解@AsyncClassDef
@Documented
@Retention(RUNTIME)
@Target({ TYPE })
@Inherited
/**
 * @author yujiakui
 *
 *         下午3:06:31
 *
 */
public @interface AsyncClassDef {

    /**
     * 異步方法列表
     *
     * @return
     */
    AsyncMethodDef[] asyncMethods() default {};

    /**
     * 類級(jí)別線程池配置
     *
     * @return
     */
    AsyncThreadPoolConfig classThreadPoolConf() default @AsyncThreadPoolConfig;

}

注解@AsyncClassDef表示的是對(duì)應(yīng)這個(gè)類需要對(duì)應(yīng)的異步宾巍,但是其中的屬性可以過(guò)濾指定的方法能夠進(jìn)行異步并行處理宏侍,如下是其對(duì)應(yīng)的屬性:
注解AsyncClassDef對(duì)應(yīng)的屬性
  • 注解@AsyncMethodDef
@Documented
@Retention(RUNTIME)
@Target({ METHOD, ElementType.ANNOTATION_TYPE })
/**
 * @author yujiakui
 *
 *         下午3:02:52
 *
 *         異步并行方法對(duì)應(yīng)的注解
 *
 */
public @interface AsyncMethodDef {

    /**
     * 方法匹配對(duì)應(yīng)的正則PatternMatchUtils
     *
     * 注意:將這個(gè)注解放在方法上則這個(gè)對(duì)應(yīng)的methodMatchRegex將不起作用,因?yàn)榇藭r(shí)就是對(duì)應(yīng)這個(gè)方法
     *
     * @return
     */
    String[] methodMatchRegex() default {};

    /**
     * 排除方法匹配模式
     *
     * 注意:將這個(gè)注解放在方法上則這個(gè)對(duì)應(yīng)的methodMatchRegex將不起作用蜀漆,因?yàn)榇藭r(shí)就是對(duì)應(yīng)這個(gè)方法
     *
     * @return
     */
    String[] excludeMethodMatchRegex() default {};

    /**
     * 默認(rèn)超時(shí)時(shí)間
     *
     * @return
     */
    long timeout() default 1000;

    /**
     * 開(kāi)啟的異步線程池中的對(duì)應(yīng)執(zhí)行的線程是否繼承當(dāng)前線程的threadLocal谅河,默認(rèn)不繼承
     *
     * @return
     */
    boolean inheritThreadLocal() default false;

    /**
     * 方法線程池配置
     *
     * @return
     */
    AsyncThreadPoolConfig methodThreadPoolConf() default @AsyncThreadPoolConfig;

}

注解@AsyncMethodDef表示的是對(duì)應(yīng)的方法是可以進(jìn)行異步并行處理,并且可以指定對(duì)應(yīng)方法的線程池信息(注意:這個(gè)線程池信息可以覆蓋類上對(duì)應(yīng)的線程池信息,類上又可以覆蓋全局線程池信息绷耍,對(duì)應(yīng)的優(yōu)先級(jí)如下 方法上 > 類上 > 全局的)吐限,下表是對(duì)應(yīng)注解的屬性:
注解AsyncMethodDef對(duì)應(yīng)的屬性
  • 注解@AsyncThreadPoolConfig
@Documented
@Retention(RUNTIME)
@Target({ ElementType.ANNOTATION_TYPE })
/**
 * @author yujiakui
 *
 *         下午3:43:29
 *
 *         異步線程池配置
 */
public @interface AsyncThreadPoolConfig {

    /**
     * 是否生效,默認(rèn)為不生效(如果方法上的線程池不生效褂始,則找類上面的诸典,如果類上面的也不生效,則只有默認(rèn)全局的)
     *
     * @return
     */
    boolean effect() default false;

    /**
     * 線程池核心線程數(shù)和最大線程數(shù)的大小崎苗,默認(rèn)是20
     *
     * @return
     */
    int poolSize() default 20;

    /**
     * 隊(duì)列大小狐粱,默認(rèn)是100
     *
     * @return
     */
    int queueSize() default 100;

    /**
     * 線程池拒絕處理策略
     *
     * @return
     */
    PoolRejectHandleMode rejectPolicy() default PoolRejectHandleMode.CALLERRUN;
}

注解@AsyncThreadPoolConfig表示的線程池對(duì)應(yīng)的配置屬性信息,具體屬性信息如下表所示:
注解AsyncThreadPoolConfig對(duì)應(yīng)的屬性

其中對(duì)應(yīng)的PoolRejectHandleMode對(duì)象是一個(gè)枚舉類型胆数,目前主要提供了兩種類型:REJECT(線程池隊(duì)列滿了之后再來(lái)請(qǐng)求直接拒絕)和CALLERRUN(用于被拒絕任務(wù)的處理程序肌蜻,它直接在 execute 方法的調(diào)用線程中運(yùn)行被拒絕的任務(wù);如果執(zhí)行程序已關(guān)閉必尼,則會(huì)丟棄該任務(wù))

  • 注解@EnableAsyncClass
@Documented
@Retention(RUNTIME)
@Target({ TYPE })
@Inherited
/**
 * @author yujiakui
 *
 *         上午11:35:46
 *
 */
public @interface EnableAsyncClass {

    /**
     * 異步并行類方法信息列表
     *
     * @return
     */
    EnableAsyncClassMethodInfo[] classMethodInfos() default { @EnableAsyncClassMethodInfo };
}

注解@EnableAsyncClass表示的是對(duì)應(yīng)的類開(kāi)啟對(duì)應(yīng)的異步并行蒋搜,也就是只要被這個(gè)類調(diào)用的方法,只要被調(diào)用方法支持對(duì)應(yīng)的異步并行調(diào)用判莉,在這個(gè)類中就可以被異步并行調(diào)用了豆挽,對(duì)應(yīng)的屬性如下表所示:
注解@EnableAsyncClass對(duì)應(yīng)的屬性信息
  • 注解@EnableAsyncClassMethodInfo
@Documented
@Retention(RUNTIME)
@Target(TYPE_USE)
/**
 * @author yujiakui
 *
 *         上午11:44:26
 *
 *         開(kāi)啟異步并行類方法信息
 */
public @interface EnableAsyncClassMethodInfo {

    /**
     * 對(duì)應(yīng)類的全名,默認(rèn)是ALL券盅,就是全部(即是標(biāo)記了異步并行定義的類)
     *
     * @return
     */
    String classFullName() default AsyncLoadAnnotationConstants.ALL_CLASSES;

    /**
     * 默認(rèn)全部標(biāo)記定義了所有異步并行加載的方法
     *
     * @return
     */
    String[] methodMatchRegex() default { AsyncLoadAnnotationConstants.ALL_METHODS };
}

注解@EnableAsyncClassMethodInfo表示的是開(kāi)啟異步并行調(diào)用對(duì)應(yīng)的類和方法信息帮哈,就是開(kāi)啟哪些能夠被異步并行的方法信息(注意:一個(gè)是調(diào)用方A是開(kāi)啟異步并行調(diào)用,另一個(gè)是B和C定義了能夠被并行異步調(diào)用锰镀,對(duì)于定義了能夠進(jìn)行異步并行調(diào)用的方法但汞,只有在調(diào)用方開(kāi)啟了異步調(diào)用才起作用),對(duì)應(yīng)的注解屬性信息如下:
注解@EnableAsyncClassMethodInfo對(duì)應(yīng)的屬性
  • 注解@EnableAsyncMethod
@Documented
@Retention(RUNTIME)
@Target(METHOD)
/**
 * @author yujiakui
 *
 *         下午3:54:02
 *
 */
public @interface EnableAsyncMethod {

    /**
     * 異步并行類方法信息列表
     *
     * @return
     */
    EnableAsyncClassMethodInfo[] classMethodInfos() default { @EnableAsyncClassMethodInfo };

}

注解@ EnableAsyncMethod開(kāi)啟異步并行調(diào)用的方法互站,即是被這個(gè)開(kāi)啟異步并行方法調(diào)用的方法開(kāi)啟對(duì)應(yīng)的異步并行調(diào)用,比如如果方法A開(kāi)啟了異步并行調(diào)用僵缺,并行方法A調(diào)用了方法B和C胡桃,且B和C都是定義了能夠進(jìn)行異步并行調(diào)用的,則可以在方法A中實(shí)現(xiàn)B和C對(duì)應(yīng)的異步并行方法調(diào)用(前提是A開(kāi)啟的方法對(duì)應(yīng)的屬性配置中包括B和C)磕潮,注解EnableAsyncMethod對(duì)應(yīng)的屬性如下表所示:
注解@ EnableAsyncMethod對(duì)應(yīng)的屬性信息
  • 類AsyncAnnotationParserFactory
    類AsyncAnnotationParserFactory主要的功能則是解析注解AsyncClassDef翠胰,AsyncMethodDef和AsyncThreadPoolConfig,通過(guò)解析他們獲得那些定義了能夠進(jìn)行異步并行調(diào)用的配置信息自脯;并且此類還可以從全局的配置信息中獲取對(duì)應(yīng)的異步并行全局的線程池配置之景。
  • 類AsyncLoadHandleFactory
    類AsyncLoadHandleFactory主要的功能是根據(jù)類AsyncAnnotationParserFactory解析注解得到的異步并行調(diào)用的配置信息,來(lái)對(duì)具體方法調(diào)用進(jìn)行攔截并開(kāi)啟對(duì)應(yīng)的異步并行調(diào)度(開(kāi)啟線程池和cglib包裝對(duì)應(yīng)的返回結(jié)果)膏潮。
  • 類AsyncLoadHandlerAdvice
    類AsyncLoadHandlerAdvice主要的功能是攔截標(biāo)記了注解@AsyncClassDef的類锻狗,并對(duì)應(yīng)其中標(biāo)記了@AsyncMethodDef的方法進(jìn)行異步并行調(diào)用,在進(jìn)行異步并行調(diào)用之前,還要經(jīng)過(guò)是否開(kāi)啟異步并行調(diào)用的判斷轻纪,如果沒(méi)有開(kāi)啟油额,則不會(huì)進(jìn)行異步并行調(diào)用。
  • 類AsyncLoadEnableAdvice
    類AsyncLoadEnableAdvice主要的功能是攔截標(biāo)記了注解@ EnableAsyncClass的類刻帚,并對(duì)注解@EnableAsyncClassMethodInfo和@EnableAsyncMethod進(jìn)行解析獲得對(duì)應(yīng)的開(kāi)啟異步并行調(diào)用的配置信息潦嘶,這個(gè)配置信息通過(guò)ThreadLocal傳給類AsyncLoadHandlerAdvice進(jìn)行異步并行調(diào)用之前的開(kāi)啟功能判斷。

2.2對(duì)應(yīng)的處理流程

對(duì)應(yīng)整體調(diào)用的序列圖如下:
整體流程圖

3. 使用

  • 定義可以進(jìn)行異步并行調(diào)用的方法崇众,如下所示:
@Component
@AsyncClassDef
public class AsyncLoadAnnotationTestServiceImpl extends AsyncLoadTestServiceImpl {

    @Override
    @AsyncMethodDef(timeout = 10)
    public AsyncLoadTestModel getRemoteModel(String name, long sleep) {
        return super.getRemoteModel(name, sleep);
    }
}
  • 開(kāi)啟對(duì)應(yīng)的異步并行調(diào)用掂僵,如下所示:
@Component
@EnableAsyncClass
public class AsyncLoadAnnotationMultiMethodTest {

    @Autowired
    private AsyncLoadAnnotationTestServiceImpl asyncLoadAnnotationTestServiceImpl;

    @EnableAsyncMethod
    public List<AsyncLoadTestModel> multiHandler(String name, long sleep) {

        List<AsyncLoadTestModel> results = Lists.newArrayList();
        for (int i = 0; i < 5; i++) {
            AsyncLoadTestModel model = asyncLoadAnnotationTestServiceImpl.getRemoteModel(name,
                    sleep);

            results.add(model);
        }
        return results;
    }
}
  • 測(cè)試
public class AsyncLoadAnnotationMultiTest {

    public static void main(String[] args) {
        AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(
                "com.alibaba.asyncload.impl.annotation",
                "com.alibaba.asyncload.annotation",
                "com.alibaba.asyncload.domain");
        // 執(zhí)行測(cè)試
        AsyncLoadAnnotationMultiMethodTest service = annotationConfigApplicationContext
                .getBean(AsyncLoadAnnotationMultiMethodTest.class);
        List<AsyncLoadTestModel> models = service.multiHandler("xxx", 10000);
        long start = 0, end = 0;
        for (AsyncLoadTestModel model : models) {
            start = System.currentTimeMillis();
            System.out.println(model.getDetail());
            end = System.currentTimeMillis();
            System.out.println("costTime:" + (end - start));
        }
    }
}

四、源碼地址

https://github.com/lwjaiyjk/asyncload.git

參考:
[1] https://github.com/alibaba/asyncload.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末顷歌,一起剝皮案震驚了整個(gè)濱河市锰蓬,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌衙吩,老刑警劉巖互妓,帶你破解...
    沈念sama閱讀 212,884評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異坤塞,居然都是意外死亡冯勉,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)摹芙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)灼狰,“玉大人,你說(shuō)我怎么就攤上這事浮禾〗慌撸” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,369評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵盈电,是天一觀的道長(zhǎng)蝴簇。 經(jīng)常有香客問(wèn)我,道長(zhǎng)匆帚,這世上最難降的妖魔是什么熬词? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,799評(píng)論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮吸重,結(jié)果婚禮上互拾,老公的妹妹穿的比我還像新娘。我一直安慰自己嚎幸,他們只是感情好颜矿,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著嫉晶,像睡著了一般骑疆。 火紅的嫁衣襯著肌膚如雪田篇。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,096評(píng)論 1 291
  • 那天封断,我揣著相機(jī)與錄音斯辰,去河邊找鬼。 笑死坡疼,一個(gè)胖子當(dāng)著我的面吹牛彬呻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播柄瑰,決...
    沈念sama閱讀 39,159評(píng)論 3 411
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼闸氮,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了教沾?” 一聲冷哼從身側(cè)響起蒲跨,我...
    開(kāi)封第一講書(shū)人閱讀 37,917評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎授翻,沒(méi)想到半個(gè)月后或悲,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,360評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堪唐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評(píng)論 2 327
  • 正文 我和宋清朗相戀三年巡语,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片淮菠。...
    茶點(diǎn)故事閱讀 38,814評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡男公,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出合陵,到底是詐尸還是另有隱情枢赔,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評(píng)論 4 334
  • 正文 年R本政府宣布拥知,位于F島的核電站踏拜,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏低剔。R本人自食惡果不足惜速梗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評(píng)論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望户侥。 院中可真熱鬧,春花似錦峦嗤、人聲如沸蕊唐。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,882評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)替梨。三九已至钓试,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間副瀑,已是汗流浹背弓熏。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,123評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留糠睡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,641評(píng)論 2 362
  • 正文 我出身青樓狈孔,卻偏偏與公主長(zhǎng)得像信认,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子均抽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,871評(píng)論 25 707
  • 我有一個(gè)夢(mèng) 嫁赏,
    qjc你在哪里呀閱讀 150評(píng)論 0 1
  • 萬(wàn)能的神, 請(qǐng)恩準(zhǔn)我把你信仰油挥! 原諒我 在此刻才感念你的韶光潦蝇! 用圣潔的心對(duì)你忠誠(chéng)。 但愿能拭去 年少時(shí)對(duì)你的謾罵...
    隔壁貓閱讀 468評(píng)論 0 0
  • 當(dāng)今社會(huì)的寵兒無(wú)非商人和演員
    軼趣味閱讀 234評(píng)論 0 0
  • 又到了一學(xué)年結(jié)束深寥,自己開(kāi)始總結(jié)一年得失攘乒,只覺(jué)得有太多說(shuō)錯(cuò)的話,做錯(cuò)的事翩迈,未深讀的書(shū)持灰。懊悔之余,看一眼朋友圈负饲,那些早...
    單單閱讀 307評(píng)論 0 2