2、使用SPRING中的執行緒池ThreadPoolTaskExecutor實現JAVA併發
new Thread的弊端如下:
a. 每次new Thread新建物件效能差。
b. 執行緒缺乏統一管理,可能無限制新建執行緒,相互之間競爭,及可能佔用過多系統資源導致宕機或oom。
c. 缺乏更多功能,如定時執行、定期執行、執行緒中斷。
相比new Thread,Java提供的四種執行緒池的好處在於:
a. 重用存在的執行緒,減少物件建立、消亡的開銷,效能佳。
b. 可有效控制最大併發執行緒數,提高系統資源的使用率,同時避免過多資源競爭,避免堵塞。
c. 提供定時執行、定期執行、單執行緒、併發數控制等功能。
1、java執行緒池
Java通過Executors提供四種執行緒池,分別為:
newCachedThreadPool建立一個可快取執行緒池,如果執行緒池長度超過處理需要,可靈活回收空閒執行緒,若無可回收,則新建執行緒。
newFixedThreadPool 建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待。
newScheduledThreadPool 建立一個定長執行緒池,支援定時及週期性任務執行。
newSingleThreadExecutor 建立一個單執行緒化的執行緒池,它只會用唯一的工作執行緒來執行任務,保證所有任務按照指定順序(FIFO, LIFO, 優先順序)執行。
package com.java.my; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; /** * @author wanjiadong * @description * @date Create in 14:01 2018/2/1 */ public class test2 { public static void main(String[] args) throws InterruptedException { //建立一個定長執行緒池,可控制執行緒最大併發數,超出的執行緒會在佇列中等待 ExecutorService executorService = Executors.newFixedThreadPool(3); long beginTime = System.currentTimeMillis(); for(int i =0;i<10;i++){ System.out.println("建立執行緒:"+i); final int index = i; Runnable run = new Runnable() { @Override public void run() { System.out.println("啟動執行緒:"+index); } }; // 在未來某個時間執行給定的命令 executorService.execute(run); } //關閉啟動執行緒 executorService.shutdown(); //等待子執行緒結束,再執行下面程式碼 executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); System.out.println("所有執行緒都結束了,用時為:"+(System.currentTimeMillis()-beginTime)); } }
2、使用SPRING中的執行緒池ThreadPoolTaskExecutor實現JAVA併發
ThreadPoolTaskExecutor的引數:
int corePoolSize:執行緒池維護執行緒的最小數量.
int maximumPoolSize:執行緒池維護執行緒的最大數量.
long keepAliveTime:空閒執行緒的存活時間.
TimeUnit unit: 時間單位,現有納秒,微秒,毫秒,秒列舉值.
BlockingQueue<Runnable> workQueue:持有等待執行的任務佇列.
RejectedExecutionHandler handler: 用來拒絕一個任務的執行,有兩種情況會發生這種情況。
一是在execute方法中若addIfUnderMaximumPoolSize(command)為false,即執行緒池已經飽和;
二是在execute方法中, 發現runState!=RUNNING || poolSize == 0,即已經shutdown,就呼叫ensureQueuedTaskHandled(Runnable command),在該方法中有可能呼叫reject。
ThredPoolTaskExcutor的處理流程:
當池子大小小於corePoolSize,就新建執行緒,並處理請求
當池子大小等於corePoolSize,把請求放入workQueue中,池子裡的空閒執行緒就去workQueue中取任務並處理
當workQueue放不下任務時,就新建執行緒入池,並處理請求,如果池子大小撐到了maximumPoolSize,就用RejectedExecutionHandler來做拒絕處理
當池子的執行緒數大於corePoolSize時,多餘的執行緒會等待keepAliveTime長時間,如果無請求可處理就自行銷燬
其會優先建立 CorePoolSiz 執行緒, 當繼續增加執行緒時,先放入Queue中,當 CorePoolSiz 和 Queue 都滿的時候,就增加建立新執行緒,當執行緒達到MaxPoolSize的時候,就會丟擲錯 誤 org.springframework.core.task.TaskRejectedException
另外MaxPoolSize的設定如果比系統支援的執行緒數還要大時,會丟擲java.lang.OutOfMemoryError: unable to create new native thread 異常。
<!-- 非同步執行緒池 -->
<bean id="threadPool"
class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton">
<!-- 核心執行緒數 -->
<property name="corePoolSize" value="10" />
<!-- 最大執行緒數 -->
<property name="maxPoolSize" value="50" />
<!-- 佇列最大長度 >=mainExecutor.maxSize -->
<property name="queueCapacity" value="10" />
<!-- 執行緒池維護執行緒所允許的空閒時間 -->
<property name="keepAliveSeconds" value="300" />
<!-- 執行緒池對拒絕任務(無執行緒可用)的處理策略 -->
<property name="rejectedExecutionHandler">
<bean class="java.util.concurrent.ThreadPoolExecutor$CallerRunsPolicy"/>
</property>
</bean>
使用
1,初始化執行緒池
//非同步執行緒池
@Autowired
private ThreadPoolTaskExecutor threadPool;
2,線上程池中執行某個執行緒
threadPool.execute(new Runnable() {...});