最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于Spring中的線程池和定時(shí)任務(wù)功能解析

 更新時(shí)間:2017年09月13日 08:44:45   作者:HelloWorld1992  
下面小編就為大家?guī)硪黄赟pring中的線程池和定時(shí)任務(wù)功能解析。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧

1.功能介紹

Spring框架提供了線程池和定時(shí)任務(wù)執(zhí)行的抽象接口:TaskExecutor和TaskScheduler來支持異步執(zhí)行任務(wù)和定時(shí)執(zhí)行任務(wù)功能。同時(shí)使用框架自己定義的抽象接口來屏蔽掉底層JDK版本間以及Java EE中的線程池和定時(shí)任務(wù)處理的差異。
另外Spring還支持集成JDK內(nèi)部的定時(shí)器Timer和Quartz Scheduler框架。

2.線程池的抽象:TaskExecutor

TaskExecutor涉及到的相關(guān)類圖如下:



TaskExecutor接口源代碼如下所示:

public interface TaskExecutor extends Executor {

 /**
  * Execute the given {@code task}.
  * <p>The call might return immediately if the implementation uses
  * an asynchronous execution strategy, or might block in the case
  * of synchronous execution.
  * @param task the {@code Runnable} to execute (never {@code null})
  * @throws TaskRejectedException if the given task was not accepted
  */
 @Override
 void execute(Runnable task);

}

此接口和Executor幾乎完全一樣,只定義了一個(gè)接收Runnable參數(shù)的方法,據(jù)Spring官方介紹此接口最初是為了在其他組建中使用線程時(shí),將JKD抽離出來而設(shè)計(jì)的。在Spring的一些其他組件中比如ApplicationEventMulticaster,Quartz都是使用TaskExecutor來作為線程池的抽象的。

3.Spring提供的TaskExecutor的實(shí)現(xiàn)類

org.springframework.core.task.SimpleAsyncTaskExecutor

此實(shí)現(xiàn)支持任務(wù)的異步執(zhí)行,但是此實(shí)現(xiàn)沒有線程的復(fù)用,每次執(zhí)行一個(gè)提交的任務(wù)時(shí)候都會(huì)新建一個(gè)線程,任務(wù)執(zhí)行完成后會(huì)將線程關(guān)閉,最大并發(fā)數(shù)默認(rèn)是沒有限制的,但是可以通過調(diào)用下面的方法來設(shè)置最大并發(fā)數(shù)。一般使用線程池來代替此實(shí)現(xiàn),特別是執(zhí)行一些生命周期很短的任務(wù)的時(shí)候。

public void setConcurrencyLimit(int concurrencyLimit) {
  this.concurrencyThrottle.setConcurrencyLimit(concurrencyLimit);
 }

Spring還提供了同步任務(wù)執(zhí)行的實(shí)現(xiàn)類:

 org.springframework.core.task.SyncTaskExecutor

此類中只有一個(gè)方法,代碼如下:

@Override
 public void execute(Runnable task) {
  Assert.notNull(task, "Runnable must not be null");
  task.run();
 }

此方法中直接調(diào)用傳入的Runable對(duì)象的run方法,因此在執(zhí)行此方法的時(shí)候不會(huì)另外開啟新的線程,只是普通的方法調(diào)用,同步執(zhí)行提交的Runable對(duì)象。

Spring有兩個(gè)線程池的實(shí)現(xiàn)類,分別為:SimpleThreadPoolTaskExecutor和ThreadPoolTaskExecutor,其中當(dāng)我們有Quarts和非Quarts共享同一個(gè)線程池的需求的時(shí)候使用SimpleThreadPoolTaskExecutor,除了這種情況,我們一般是使用
ThreadPoolTaskExecutor,此實(shí)現(xiàn)可以通過屬性注入來配置線程池的相關(guān)配置。 ThreadPoolTaskExecutor中屬性注入的源碼如下:此配置可以在運(yùn)行期修改,代碼中修改過程使用了同步控制。

/**
 * Set the ThreadPoolExecutor's core pool size.
 * Default is 1.
 * <p><b>This setting can be modified at runtime, for example through JMX.</b>
 */
public void setCorePoolSize(int corePoolSize) {
 synchronized (this.poolSizeMonitor) {
  this.corePoolSize = corePoolSize;
  if (this.threadPoolExecutor != null) {
   this.threadPoolExecutor.setCorePoolSize(corePoolSize);
  }
 }
}

4.TaskExecutor使用Demo

首先定義一個(gè)任務(wù)如下所示:

public class DataSimulation implements Runnable{

 private HourAverageValueDao hourAverageValueDao;

 @Override
 public void run() {

  Random random = new Random();
  AverageValue averageValue = new AverageValue();
  averageValue.setAverageVaule(random.nextInt(100));
  averageValue.setCreatedTime(new Date());
  hourAverageValueDao.insert(averageValue);

 }
}

此任務(wù)中產(chǎn)生一個(gè)隨機(jī)數(shù),并封裝成一個(gè)類對(duì)象,并將此數(shù)據(jù)插入到數(shù)據(jù)庫中。

然后需要定一個(gè)類,使用TaskExecutor,代碼如下:

public class DataFacotory {

 private TaskExecutor executor;

 public TaskExecutor getExecutor() {
  return executor;
 }

 public void setExecutor(TaskExecutor executor) {
  this.executor = executor;
 }

 public void dataFactory(){

  for (int i =0; i < 10; i++){
   executor.execute(new DataSimulation());
  }
 }
}

此類中定義了TaskExecutor的屬性,并定一個(gè)方法,此方法中提交10個(gè)任務(wù)到TaskExecutor,下面只需配置Spring文件,注入TaskExecutor就可以實(shí)現(xiàn)線程池的使用。配置文件如下所示:

<bean id = "taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
  <property name="corePoolSize" value = "5"></property>
  <property name = "maxPoolSize" value="10"></property>
  <property name="queueCapacity" value="25"></property>
 </bean>

完成配置后即可使用此線程池。Spring提供的線程池可以通過配置文件配置線程池的配置,相比JDk自帶的線程池是一個(gè)很大的優(yōu)勢。

5.為什么使用線程池

1.通過使用線程池來實(shí)現(xiàn)線程的復(fù)用,減少線程創(chuàng)建和銷毀的開銷

2.將執(zhí)行線程的任務(wù)交給線程池來操作,一定意義上實(shí)現(xiàn)了解耦

3.使用線程池可以控制任務(wù)的最大并發(fā)數(shù)目,這個(gè)在防止內(nèi)存溢出以及并發(fā)優(yōu)化方面有很重要的作用。

6.定時(shí)任務(wù)抽象類:TaskScheduler

TaskScheduler接口源代碼如下:

public interface TaskScheduler {
 //通過觸發(fā)器來決定task是否執(zhí)行
ScheduledFuture schedule(Runnable task, Trigger trigger);
//在starttime的時(shí)候執(zhí)行一次
ScheduledFuture schedule(Runnable task, Date startTime);
從starttime開始每個(gè)period時(shí)間段執(zhí)行一次task
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
每隔period執(zhí)行一次
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
從startTime開始每隔delay長時(shí)間執(zhí)行一次
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
每隔delay時(shí)間執(zhí)行一次
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}

指定開始時(shí)間的接口,如果時(shí)間已經(jīng)是過去的某一時(shí)間點(diǎn),則此任務(wù)會(huì)馬上執(zhí)行一次。以上幾種執(zhí)行方式傳入Trigger的方式是用的最多的,Trigger接口中只定義了一個(gè)方法:

Date nextExecutionTime(TriggerContext triggerContext);

其中參數(shù)類型TriggerContext的定義如下:

public interface TriggerContext {

/**
 * Return the last <i>scheduled</i> execution time of the task,
 * or {@code null} if not scheduled before.
 */
Date lastScheduledExecutionTime();

/**
 * Return the last <i>actual</i> execution time of the task,
 * or {@code null} if not scheduled before.
 */
Date lastActualExecutionTime();

/**
 * Return the last completion time of the task,
 * or {@code null} if not scheduled before.
 */
Date lastCompletionTime();

}

提供了獲取上一次任務(wù)執(zhí)行信息的接口。我們通過實(shí)現(xiàn)Trigger接口可以實(shí)現(xiàn)自定義觸發(fā)器來執(zhí)行執(zhí)行task。當(dāng)然Spring也提供了兩個(gè)默認(rèn)的實(shí)現(xiàn)類:PeriodicTrigger和CronTrigger。

7.TaskScheduler定時(shí)任務(wù)Demo

首先在Spring配置文件中啟用注解配置如下:

<task:annotation-driven scheduler="myScheduler"/> //指定scheduler屬性是可選項(xiàng),不添加也可以正常使用
<task:scheduler id="myScheduler" pool-size="10"/>

然后創(chuàng)建service,并在service中使用@Scheduled注解創(chuàng)建定時(shí)任務(wù),代碼如下:

@Component
public class SchedulerPoolTest {

 @Scheduled(cron = "0 * * * * ?")
 public void task1(){
  System.out.println("test");
  Thread thread = Thread.currentThread();
  System.out.println("ThreadName:" + thread.getName() + ",id:" + thread.getId() + ",group:" + thread.getThreadGroup());

 }

 @Scheduled(fixedDelay = 5000)
 public void task2(){
  System.out.println("test");
  Thread thread = Thread.currentThread();
  System.out.println("ThreadName:" + thread.getName() + ",id:" + thread.getId() + ",group:" + thread.getThreadGroup());

 }

}

只是添加以上內(nèi)容可能還不能正常執(zhí)行task,還需要注意以下兩點(diǎn):

1.必須將SchedulerPoolTest類包含在spring所掃描的包里面

配置如下:

<context:component-scan base-package="com.zjut.task" />

2.需要在web.xml中添加spring配置文件的監(jiān)聽器,代碼如下:

<context-param>
 <param-name>contextConfigLocation</param-name>
 <param-value>classpath*:spring-task.xml</param-value>
 </context-param>

 <listener>
 <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

添加以上內(nèi)容后,啟動(dòng)服務(wù)器,將會(huì)定時(shí)執(zhí)行任務(wù)。

8.Cron表達(dá)式

Cron表達(dá)式由6個(gè)字符串組成,每個(gè)字符串分別代表:

{秒} {分} {時(shí)} {日} {月} {周}

其中每個(gè)字符串所允許的取值范圍為:

字段名     允許的值      允許的特殊字符 
秒     0-59       , - * / 
分     0-59       , - * / 
小時(shí)     0-23       , - * / 
日     1-31       , - * ? / L W C 
月     1-12 or JAN-DEC     , - * / 
周幾     1-7 or SUN-SAT     , - * ? / L C #

常用的Cron表達(dá)式:

"0 10,44 14 ? 3 WED" 每年三月的星期三的下午2:10和2:44觸發(fā)
"0 0/5 14,18 * * ?" 在每天下午2點(diǎn)到2:55期間和下午6點(diǎn)到6:55期間的每5分鐘觸發(fā)
"15-30/5 * * * * ?" 每分鐘的15秒到30秒之間開始觸發(fā),每隔5秒觸發(fā)一次
"0 15 10 ? * 5#3" 每個(gè)月第三周的星期四的10點(diǎn)15分0秒觸發(fā)任務(wù)

注:問號(hào)是用于避免日和周的設(shè)定由沖突而用的,當(dāng)其中一個(gè)設(shè)置了具體的值,另外一個(gè)必須使用?。另外推薦一個(gè)Cron表達(dá)式生成的鏈接:http://www.cronmaker.com/

9.@Async注解

Async注解提供了異步調(diào)用方法的功能,當(dāng)調(diào)用由此注解的方法的時(shí)候方法調(diào)用者會(huì)馬上返回而不會(huì)等待調(diào)用的方法執(zhí)行完成,被調(diào)用的方法會(huì)從線程池中分配一個(gè)線程來執(zhí)行此方法。

10.Spring定時(shí)任務(wù)中并發(fā)執(zhí)行的問題

同一個(gè)任務(wù),當(dāng)上一個(gè)任務(wù)沒有執(zhí)行完成的時(shí)候,新的任務(wù)不會(huì)執(zhí)行。

不同任務(wù)的情況下:TODO...

以上這篇基于Spring中的線程池和定時(shí)任務(wù)功能解析就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • JAVA如何判斷上傳文件后綴名是否符合規(guī)范MultipartFile

    JAVA如何判斷上傳文件后綴名是否符合規(guī)范MultipartFile

    這篇文章主要介紹了JAVA判斷上傳文件后綴名是否符合規(guī)范MultipartFile,文中通過實(shí)例代碼介紹了java實(shí)現(xiàn)對(duì)上傳文件做安全性檢查,需要的朋友可以參考下
    2023-11-11
  • 簡單了解java volatile

    簡單了解java volatile

    這篇文章主要介紹了了解java volatile,volatile是Java提供的一種輕量級(jí)的同步機(jī)制,在并發(fā)編程中,它也扮演著比較重要的角色。下面我們來一起學(xué)習(xí)一下吧
    2019-05-05
  • 分布式開發(fā)醫(yī)療掛號(hào)系統(tǒng)數(shù)據(jù)字典模塊前后端實(shí)現(xiàn)

    分布式開發(fā)醫(yī)療掛號(hào)系統(tǒng)數(shù)據(jù)字典模塊前后端實(shí)現(xiàn)

    這篇文章主要為大家介紹了分布式開發(fā)醫(yī)療掛號(hào)系統(tǒng)數(shù)據(jù)字典模塊前后端實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-04-04
  • 案例講解SpringBoot?Starter的使用教程

    案例講解SpringBoot?Starter的使用教程

    SpringBoot中的starter是一種非常重要的機(jī)制,能夠拋棄以前繁雜的配置,將其統(tǒng)一集成進(jìn)starter,應(yīng)用者只需要在maven中引入starter依賴,SpringBoot就能自動(dòng)掃描到要加載的信息并啟動(dòng)相應(yīng)的默認(rèn)配置,本文通過案例講解SpringBoot?Starter的使用,感興趣的朋友一起看看吧
    2023-12-12
  • Java?9中的"菱形"語法詳解

    Java?9中的"菱形"語法詳解

    Java?9?再次增強(qiáng)了“菱形”語法,它甚至允許在創(chuàng)建匿名內(nèi)部類時(shí)使用菱形語法,Java?可根據(jù)上下文來推斷匿名內(nèi)部類中泛型的類型,下面程序示范了在匿名內(nèi)部類中使用菱形語法,感興趣的朋友跟隨小編一起看看吧
    2023-06-06
  • Redisson之分布式鎖原理全面分析

    Redisson之分布式鎖原理全面分析

    這篇文章主要介紹了Redisson分布式鎖原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-03-03
  • java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具

    java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)字符串和數(shù)字轉(zhuǎn)換工具,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-04-04
  • SpringBoot+MyBatis-Plus+Velocity實(shí)現(xiàn)代碼自動(dòng)生成

    SpringBoot+MyBatis-Plus+Velocity實(shí)現(xiàn)代碼自動(dòng)生成

    本文主要介紹了使用SpringBoot、MyBatis-Plus和Velocity模板引擎實(shí)現(xiàn)代碼自動(dòng)生成器,該生成器能夠根據(jù)數(shù)據(jù)庫表結(jié)構(gòu)自動(dòng)生成增刪改查操作的代碼,感興趣的可以了解一下
    2025-03-03
  • Maven遠(yuǎn)程倉庫地址修改實(shí)現(xiàn)解析

    Maven遠(yuǎn)程倉庫地址修改實(shí)現(xiàn)解析

    這篇文章主要介紹了Maven遠(yuǎn)程倉庫地址修改實(shí)現(xiàn)解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-11-11
  • Java多線程及線程安全實(shí)現(xiàn)方法解析

    Java多線程及線程安全實(shí)現(xiàn)方法解析

    這篇文章主要介紹了Java多線程及線程安全實(shí)現(xiàn)方法解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-06-06

最新評(píng)論

陕西省| 浠水县| 保亭| 陕西省| 巴彦淖尔市| 泰来县| 景泰县| 石棉县| 饶平县| 黑水县| 黄大仙区| 威远县| 甘肃省| 大姚县| 上林县| 襄樊市| 无棣县| 正蓝旗| 喀喇| 乌鲁木齐县| 安阳县| 盐城市| 安平县| 平山县| 贺州市| 安阳县| 紫阳县| 湖口县| 徐水县| 醴陵市| 阿勒泰市| 巨野县| 陕西省| 家居| 华安县| 雅安市| 安泽县| 舞钢市| 车致| 五台县| 瑞昌市|