1. 程式人生 > 實用技巧 >java 執行緒池、多執行緒併發實戰(生產者消費者模型 1 vs 10) 附案例原始碼

java 執行緒池、多執行緒併發實戰(生產者消費者模型 1 vs 10) 附案例原始碼

執行緒池

為什麼要使用執行緒池

  例如web伺服器、資料庫伺服器、檔案伺服器或郵件伺服器之類的。請求的時候,單個任務時間很短,但是請求數量巨大。每一次請求,就會建立一個新執行緒,然後在新執行緒中請求服務,頻繁的建立執行緒,銷燬執行緒造成系統很大的開銷,資源的浪費。

  執行緒池為執行緒生命週期開銷問題和資源不足問題提供瞭解決方案。通過對多個任務重用執行緒,執行緒車建立的開銷分攤到多個任務上。

建立與使用

Future

  對具體的Runnable或者Callable任務的執行結果進行取消、查詢是否完成、獲取結果、設定結果。get方法會阻塞,直到任務返回結果。

Callable&FutureTask

  Callable與Runnable功能相似,Callable有返回值;Runnable沒有返回值;一般情況下,Callable與FutureTask一起使用,或者與執行緒池一起使用

執行緒池核心組成部分

  • corePoolSize:核心執行緒池大小
  • maximumPoolSize:執行緒池最大容量
  • KeepAliveTime:當執行緒數量大於核心時,多餘的空閒執行緒在終止之前等待新任務的最大時間
  • unit:時間單位
  • workQueue:工作佇列
  • ThreadFactory:執行緒工廠
  • handler:拒絕策略

Executor框架

實戰

需求分析

業務場景

  一般系統,多數會與第三方系統的資料進行打交道,而第三方的生產庫,並不允許我們直接操作。在企業裡面,一般都是通過中間表進行同步,即第三方系統將生產資料放入一張與其生產環境隔離的另一個獨立資料庫中的獨立表,在根據介面協議,增加相應的欄位。而我方需要讀取該中間表中的資料,並對資料進行同步操作。此時就需要編寫相應的程式進行資料同步。

同步方式

  1. 全量同步:每天定時將當天的生產資料全部同步過來(優點:實現檢點;缺點:資料同步不及時)
  2. 增量同步:每新增一條,便將該資料同步過來(優點:資料接近實時同步;缺點:實現相對困難)

我方需要做的事情

  讀取中間表的資料,並同步到業務系統中

模型抽離(生產者消費者模型)

  1. 生產者:讀取中間表的資料
  2. 消費者:消費生產者生產的資料

介面協議的制定

  1. 取我方業務上需要用到的欄位
  2. 需要有欄位記錄資料什麼時候進入中間表
  3. 增加相應的資料標誌位,用於標誌資料的同步狀態
  4. 記錄資料的同步時間

技術選型

  1. mybatis
  2. 單一生產者多消費者
  3. 多執行緒併發操作

中間表設計

專案搭建

專案結構

pom.xml

pom.xml

log4j.properties

log4j.properties

middle-student.xml

middle-student.xml

test-student.xml

test-student.xml

mybatis-config-middle.xml

mybatis-config-middle.xml

mybatis-config-test.xml

mybatis-config-test.xml

StudentConst.java

StudentConst.java

DruidDataSourceFactory.java

DruidDataSourceFactory.java

Student.java(middle包下)

student.java

Student.java(test包下)

Student.java

MiddleProcess.java

MiddleProcess.java

TestProcess.java

TestProcess.java

MiddleProcessImpl.java

MiddleProcessImpl.java

TestProcessImpl.java

TestProcessImpl.java

Consumer.java

Consumer.java

Producer.java

Producer.java

Main.java

Main.java

SqlSessionUtil.java

SqlSessionUtil.java

sql指令碼

middle.student

test.student

演示

部署如何啟動指定main

修改pom.xml

  mainClass指定啟動包下的main

 <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <!-- 預設啟動 程式,mainClass指定啟動的main函式的報名 -->
                    <mainClass>com.cyb.start.Main</mainClass>
                    <layout>JAR</layout>
                    <addResources>true</addResources>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>repackage</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

修改log4j.properties日誌輸出目錄

部署