色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
电子发烧友
开通电子发烧友VIP会员 尊享10大特权
海量资料免费下载
精品直播免费看
优质内容免费畅学
课程9折专享价
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

Java多線程永動任務 多線程異步任務項目解讀

jf_ro2CN3Fa ? 來源:樓仔 ? 作者:樓仔 ? 2022-10-19 11:46 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

1. 功能說明

2. 多線程任務示例

2.1 線程池

2.2 單個任務

2.3 任務入口

2.4 結果分析

2.5 源碼地址

3. 寫在最后

大家好,今天教大家擼一個 Java 的多線程永動任務,這個示例的原型是公司自研的多線程異步任務項目 ,我把里面涉及到多線程的代碼抽離出來,然后進行一定的改造。

里面涉及的知識點非常多,特別適合有一定工作經驗 的同學學習,或者可以直接拿到項目中使用。

文章結構非常簡單:

ae8ef34e-4cfe-11ed-a3b6-dac502259ad0.png

1. 功能說明

做這個多線程異步任務,主要是因為我們有很多永動的異步任務,什么是永動呢?就是任務跑起來后,需要一直跑下去。

比如消息 Push 任務,因為一直有消息過來,所以需要一直去消費 DB 中的未推送消息,就需要整一個 Push 的永動異步任務。

我們的需求其實不難,簡單總結一下:

能同時執行多個永動的異步任務

每個異步任務,支持開多個線程 去消費這個任務的數據;

支持永動異步任務的優雅關閉 ,即關閉后,需要把所有的數據消費完畢后,再關閉。

完成上面的需求,需要注意幾個點:

每個永動任務 ,可以開一個線程去執行;

每個子任務 ,因為需要支持并發,需要用線程池控制;

永動任務的關閉,需要通知子任務的并發線程,并支持永動任務和并發子任務的優雅關閉

2. 多線程任務示例

2.1 線程池

對于子任務,需要支持并發,如果每個并發都開一個線程,用完就關閉,對資源消耗太大,所以引入線程池:

publicclassTaskProcessUtil{
//每個任務,都有自己單獨的線程池
privatestaticMapexecutors=newConcurrentHashMap<>();

//初始化一個線程池
privatestaticExecutorServiceinit(StringpoolName,intpoolSize){
returnnewThreadPoolExecutor(poolSize,poolSize,
0L,TimeUnit.MILLISECONDS,
newLinkedBlockingQueue(),
newThreadFactoryBuilder().setNameFormat("Pool-"+poolName).setDaemon(false).build(),
newThreadPoolExecutor.CallerRunsPolicy());
}

//獲取線程池
publicstaticExecutorServicegetOrInitExecutors(StringpoolName,intpoolSize){
ExecutorServiceexecutorService=executors.get(poolName);
if(null==executorService){
synchronized(TaskProcessUtil.class){
executorService=executors.get(poolName);
if(null==executorService){
executorService=init(poolName,poolSize);
executors.put(poolName,executorService);
}
}
}
returnexecutorService;
}

//回收線程資源
publicstaticvoidreleaseExecutors(StringpoolName){
ExecutorServiceexecutorService=executors.remove(poolName);
if(executorService!=null){
executorService.shutdown();
}
}
}

這是一個線程池的工具類,這里初始化線程池和回收線程資源很簡單,我們主要討論獲取線程池。

獲取線程池可能會存在并發情況,所以需要加一個 synchronized 鎖,然后鎖住后,需要對 executorService 進行二次判空校驗。

2.2 單個任務

為了更好講解單個任務的實現方式,我們的任務主要就是把 Cat 的數據打印出來,Cat 定義如下:

@Data
@Service
publicclassCat{
privateStringcatName;
publicCatsetCatName(Stringname){
this.catName=name;
returnthis;
}
}

單個任務主要包括以下功能:

獲取永動任務數據 :這里一般都是掃描 DB,我直接就簡單用 queryData() 代替。

多線程執行任務 :需要把數據拆分成 4 份,然后分別由多線程并發執行,這里可以通過線程池支持;

永動任務優雅停機 :當外面通知任務需要停機,需要執行完剩余任務數據,并回收線程資源,退出任務;

永動執行 :如果未收到停機命令,任務需要一直執行下去。

直接看代碼:

publicclassChildTask{

privatefinalintPOOL_SIZE=3;//線程池大小
privatefinalintSPLIT_SIZE=4;//數據拆分大小
privateStringtaskName;

//接收jvm關閉信號,實現優雅停機
protectedvolatilebooleanterminal=false;

publicChildTask(StringtaskName){
this.taskName=taskName;
}

//程序執行入口
publicvoiddoExecute(){
inti=0;
while(true){
System.out.println(taskName+":Cycle-"+i+"-Begin");
//獲取數據
Listdatas=queryData();
//處理數據
taskExecute(datas);
System.out.println(taskName+":Cycle-"+i+"-End");
if(terminal){
//只有應用關閉,才會走到這里,用于實現優雅的下線
break;
}
i++;
}
//回收線程池資源
TaskProcessUtil.releaseExecutors(taskName);
}

//優雅停機
publicvoidterminal(){
//關機
terminal=true;
System.out.println(taskName+"shutdown");
}

//處理數據
privatevoiddoProcessData(Listdatas,CountDownLatchlatch){
try{
for(Catcat:datas){
System.out.println(taskName+":"+cat.toString()+",ThreadName:"+Thread.currentThread().getName());
Thread.sleep(1000L);
}
}catch(Exceptione){
System.out.println(e.getStackTrace());
}finally{
if(latch!=null){
latch.countDown();
}
}
}

//處理單個任務數據
privatevoidtaskExecute(ListsourceDatas){
if(CollectionUtils.isEmpty(sourceDatas)){
return;
}
//將數據拆成4份
List>splitDatas=Lists.partition(sourceDatas,SPLIT_SIZE);
finalCountDownLatchlatch=newCountDownLatch(splitDatas.size());

//并發處理拆分的數據,共用一個線程池
for(finalListdatas:splitDatas){
ExecutorServiceexecutorService=TaskProcessUtil.getOrInitExecutors(taskName,POOL_SIZE);
executorService.submit(newRunnable(){
@Override
publicvoidrun(){
doProcessData(datas,latch);
}
});
}

try{
latch.await();
}catch(Exceptione){
System.out.println(e.getStackTrace());
}
}

//獲取永動任務數據
privateListqueryData(){
Listdatas=newArrayList<>();
for(inti=0;i

簡單解釋一下:

queryData :用于獲取數據,實際應用中其實是需要把 queryData 定為抽象方法,然后由各個任務實現自己的方法。

doProcessData :數據處理邏輯,實際應用中其實是需要把 doProcessData 定為抽象方法,然后由各個任務實現自己的方法。

taskExecute :將數據拆分成 4 份,獲取該任務的線程池,并交給線程池并發執行,然后通過 latch.await() 阻塞。當這 4 份數據都執行成功后,阻塞結束,該方法才返回。

terminal :僅用于接受停機命令,這里該變量定義為 volatile,所以多線程內存可見;

doExecute :程序執行入口,封裝了每個任務執行的流程,當 terminal=true 時,先執行完任務數據,然后回收線程池,最后退出。

2.3 任務入口

直接上代碼:

publicclassLoopTask{
privateListchildTasks;
publicvoidinitLoopTask(){
childTasks=newArrayList();
childTasks.add(newChildTask("childTask1"));
childTasks.add(newChildTask("childTask2"));
for(finalChildTaskchildTask:childTasks){
newThread(newRunnable(){
@Override
publicvoidrun(){
childTask.doExecute();
}
}).start();
}
}
publicvoidshutdownLoopTask(){
if(!CollectionUtils.isEmpty(childTasks)){
for(ChildTaskchildTask:childTasks){
childTask.terminal();
}
}
}
publicstaticvoidmain(Stringargs[])throwsException{
LoopTaskloopTask=newLoopTask();
loopTask.initLoopTask();
Thread.sleep(5000L);
loopTask.shutdownLoopTask();
}
}

每個任務都開一個單獨的 Thread,這里我初始化了 2 個永動任務,分別為 childTask1 和 childTask2,然后分別執行,后面 Sleep 了 5 秒后,再關閉任務,我們可以看看是否可以按照我們的預期優雅退出。

2.4 結果分析

執行結果如下:

childTask1:Cycle-0-Begin
childTask2:Cycle-0-Begin
childTask1:Cat(catName=羅小黑0),ThreadName:Pool-childTask1
childTask1:Cat(catName=羅小黑4),ThreadName:Pool-childTask1
childTask2:Cat(catName=羅小黑4),ThreadName:Pool-childTask2
childTask2:Cat(catName=羅小黑0),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑1),ThreadName:Pool-childTask1
childTask2:Cat(catName=羅小黑1),ThreadName:Pool-childTask2
childTask2:Cat(catName=羅小黑2),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑2),ThreadName:Pool-childTask1
childTask2:Cat(catName=羅小黑3),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑3),ThreadName:Pool-childTask1
childTask2:Cycle-0-End
childTask2:Cycle-1-Begin
childTask1:Cycle-0-End
childTask1:Cycle-1-Begin
childTask2:Cat(catName=羅小黑0),ThreadName:Pool-childTask2
childTask2:Cat(catName=羅小黑4),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑4),ThreadName:Pool-childTask1
childTask1:Cat(catName=羅小黑0),ThreadName:Pool-childTask1
childTask1shutdown
childTask2shutdown
childTask2:Cat(catName=羅小黑1),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑1),ThreadName:Pool-childTask1
childTask1:Cat(catName=羅小黑2),ThreadName:Pool-childTask1
childTask2:Cat(catName=羅小黑2),ThreadName:Pool-childTask2
childTask1:Cat(catName=羅小黑3),ThreadName:Pool-childTask1
childTask2:Cat(catName=羅小黑3),ThreadName:Pool-childTask2
childTask1:Cycle-1-End
childTask2:Cycle-1-End

輸出數據:

“Pool-childTask” 是線程池名稱;

“childTask” 是任務名稱;

“Cat(catName=羅小黑)” 是執行的結果;

“childTask shut down” 是關閉標記;

“childTask:Cycle-X-Begin” 和“childTask:Cycle-X-End” 是每一輪循環的開始和結束標記。

我們分析一下執行結果:

childTask1 和 childTask2 分別執行,在第一輪循環中都正常輸出了 5 條羅小黑數據;

第二輪執行過程中,我啟動了關閉指令,這次第二輪執行沒有直接停止,而是先執行完任務中的數據,再執行退出,所以完全符合我們的優雅退出結論。

2.5 源碼地址

GitHub 地址:

https://github.com/lml200701158/java-study/tree/master/src/main/java/com/java/parallel/pool/ofc

3. 寫在最后

對于這個經典的線程池使用示例,原項目是我好友一灰 寫的,技術水平阿里 P7級別,實現得也非常優雅,涉及的知識點非常多 ,非常值得大家學習。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • JAVA
    +關注

    關注

    20

    文章

    2988

    瀏覽量

    108846
  • 編程
    +關注

    關注

    88

    文章

    3687

    瀏覽量

    95112
  • 多線程
    +關注

    關注

    0

    文章

    279

    瀏覽量

    20399
  • 代碼
    +關注

    關注

    30

    文章

    4895

    瀏覽量

    70548
  • Thread
    +關注

    關注

    2

    文章

    88

    瀏覽量

    26525

原文標題:新來個阿里 P7,僅花 2 小時,擼出一個多線程永動任務,看完直接跪了,真牛逼!

文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關注!文章轉載請注明出處。

收藏 0人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關推薦
    熱點推薦

    Java多線程的用法

    本文將介紹一下Java多線程的用法。 基礎介紹 什么是多線程 指的是在一個進程中同時運行多個線程,每個線程都可以獨立執行不同的
    的頭像 發表于 09-30 17:07 ?1205次閱讀

    Java基礎學習多線程使用指南

    黑馬程序員-----Java基礎學習多線程
    發表于 10-08 14:10

    什么時候要使用多線程

    什么時候要使用多線程:cpu密集型:(比如一個while( true ){ i++;})IO密集型:(比如一個從磁盤拷貝數據到另一個磁盤的拷貝進程)1)計算密集型任務。此時要盡量使用多線程,可以提高
    發表于 09-06 07:25

    請問CubeMX如何配置FreeRTOS跑多線程任務

    請問CubeMX如何配置FreeRTOS跑多線程任務
    發表于 02-14 06:39

    如何使用多線程異步操作等并發設計方法來最大化程序的性能

    任務。  不過有個問題,異步有時優先級比主線程還高。這個特點和多線程不同。  原作者:jingjin221
    發表于 08-23 16:31

    java多線程編程實例 (源程序)

    java多線程編程實例 import java.awt.*;import javax.swing.*; public class CompMover extends Object { 
    發表于 10-22 11:48 ?0次下載

    java多線程設計模式_結城浩

    JAVA多線程設計模式》通過淺顯易懂的文字與實例來介紹JAVA線程相關的設計模式概念,并且通過實際的JAVA程序范例和UML圖示來一一解說
    發表于 01-05 16:15 ?0次下載
    <b class='flag-5'>java</b><b class='flag-5'>多線程</b>設計模式_結城浩

    Java多線程總結之Queue

    Java多線程應用中,隊列的使用率很高,多數生產消費模型的首選數據結構就是隊列。Java提供的線程安全的Queue可以分為 阻塞隊列和非阻塞隊列 ,其中阻塞隊列的典型例子
    發表于 11-28 16:14 ?3493次閱讀
    <b class='flag-5'>Java</b><b class='flag-5'>多線程</b>總結之Queue

    多線程好還是單線程好?單線程多線程的區別 優缺點分析

    摘要:如今單線程多線程已經得到普遍運用,那么到底多線程好還是單線程好呢?單線程多線程的區別又
    發表于 12-08 09:33 ?8.2w次閱讀

    什么是多線程編程?多線程編程基礎知識

    摘要:多線程編程是現代軟件技術中很重要的一個環節。要弄懂多線程,這就要牽涉到多進程。本文主要以多線程編程以及多線程編程相關知識而做出的一些結論。
    發表于 12-08 16:30 ?1.3w次閱讀

    java學習——java面試【事務、鎖、多線程】資料整理

    本文檔內容介紹了基于java學習java面試【事務、鎖、多線程】資料整理,供參考
    發表于 03-13 13:53 ?0次下載

    Linux下的多線程編程

    線程呢?使用多線程到底有哪些好處?什么的系統應該選用多線程?我們首先必須回答這些問題。  使用多線程的理由之一是和進程相比,它是一種非常"節儉"的多
    發表于 04-02 14:43 ?709次閱讀

    多線程如何保證數據的同步

    多線程編程是一種并發編程的方法,意味著程序中同時運行多個線程,每個線程可獨立執行不同的任務,共享同一份數據。由于多線程并發執行的特點,會引發
    的頭像 發表于 11-17 14:22 ?1658次閱讀

    java實現多線程的幾種方式

    Java實現多線程的幾種方式 多線程是指程序中包含了兩個或以上的線程,每個線程都可以并行執行不同的任務
    的頭像 發表于 03-14 16:55 ?1305次閱讀

    socket 多線程編程實現方法

    是指在同一個進程中運行多個線程,每個線程可以獨立執行任務線程共享進程的資源,如內存空間和文件句柄,但每個線程有自己的程序計數器、寄存器集合
    的頭像 發表于 11-12 14:16 ?977次閱讀
    主站蜘蛛池模板: 野花日本免费完整版高清版动漫 | 岛国大片在线播放高清 | 欧美极限扩肛 | A片毛片免费视频在线看 | A片毛片免费视频在线看 | 久久视热频这里只精品 | 亚洲 欧美 国产 伦 综合 | 一个人高清在线观看日本免费 | 麻豆高潮AV久久久久久久 | 国产亚洲精品久久久999密臂 | 野花社区视频WWW高清 | 国语自产一区第二页 | 99热国产这里只有精品免费 | 公么我好爽再深一点 | 久久久久青草大香线综合精品 | 综合激情区视频一区视频二区 | 热久久伊大人香蕉网老师 | 国产乱码精品AAAAAAAA | 亚洲精品国产熟女久久久 | 亚洲精品久久久久中文字幕二区 | 亚洲乱码国产一区三区 | 亚洲精品免播放器在线观看 | 国产三级在线精品男人的天堂 | 成片免费观看视频在线网 | 日韩欧美精品有码在线播放 | 久久精品无码一区二区日韩av | 国产剧果冻传媒星空在线观看 | 最近中文字幕完整版免费高清 | 1级午夜影院费免区 | 三级黄.色| 国产乱码免费卡1卡二卡3卡四卡 | 亚洲国产免费观看视频 | 亚洲一区免费在线观看 | 天天久久狠狠色综合 | 久艾草在线精品视频在线观看 | 看美女大腿中间的部分 | 黄页网站18以下勿看免费 | 97在线视频免费人妻 | 果冻传媒2021精品影视 | 国产小视频免费在线观看 | 国产亚洲日韩在线播放不卡 |

    電子發燒友

    中國電子工程師最喜歡的網站

    • 2931785位工程師會員交流學習
    • 獲取您個性化的科技前沿技術信息
    • 參加活動獲取豐厚的禮品