SpringBoot整合定時任務和異步任務處理

常見定時任務區別

        1、常見定時任務 Java自帶的java.util.Timer類
            timer:配置比較麻煩,時間延後問題
            timertask:不推薦

        2、Quartz框架
            配置更簡單
            xml或者註解

        3、SpringBoot使用註解方式開啓定時任務
            1)啓動類裏面 @EnableScheduling開啓定時任務,自動掃描

package net.myclass;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@MapperScan("net.myclass.mapper")
@EnableScheduling
public class MyApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(MyApplication.class, args);
    }
}


            2)定時任務業務類 加註解 @Component被容器掃描
            3)定時執行的方法加上註解 @Scheduled(fixedRate=2000) 定期執行一次

SpringBoot常用定時任務表達式配置和在線生成器

        1、cron 定時任務表達式 @Scheduled(cron="*/1 * * * * *") 表示每秒
              crontab 工具  https://tool.lu/crontab/
        2、fixedRate: 定時多久執行一次(上一次開始執行時間點後xx秒再次執行;)
        3、fixedDelay: 上一次執行結束時間點後xx秒再次執行
        4、fixedDelayString:  字符串形式,可以通過配置文件指定

package net.myclass.task;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.Date;


@Component
public class TestTask {

    @Scheduled(fixedRate = 2000)//兩秒執行一次
    public void sum(){
        System.out.println("當前時間"+new Date());
    }
}

SpringBoot2.x異步任務

                用訂單/庫存系統舉例,幾千人都在買買買,一時間幾千個訂單請求到controller,然後調用service(注:service還是跟上面一樣要幾十秒),一到service,判斷是個異步方法,於是趕緊讓處理異步任務的線程過來慢慢處理就好,controller可以直接響應用戶“訂單成功”。用戶極短時間就收到響應,於是可以繼續買買買。

                 異步:它會把需要執行的放在一個執行隊列中,像是這種需要等待的程序,他在會在執行了之後將他排在後面,然後執行其他的任務,指導它等待結束之後,執行它的回調。

                           ajax請求,在這樣的請求中會有較大的時間開銷,但是這一過程中並沒有太大的資源消耗,或者說對於javascript所執行的環境來說幾乎沒有什麼資源的消耗。所以在這樣的過程中,其實主線程是空閒着的,如果不是異步的行爲,那它所做的只有一件事,那就是等待,等待請求的響應,那麼,其實在這樣的一個過程中,完全可以把主線程在等待時候的資源開放出來進行其他的操作,這就形成了異步。

        1、使用場景:適用於處理log、發送郵件、短信……等

下單接口->查庫存 100
 餘額校驗 150
 風控用戶100
 ....


        2、啓動類裏面使用@EnableAsync註解開啓功能,自動掃描

package net.myclass;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@MapperScan("net.myclass.mapper")
@EnableScheduling
@EnableAsync
public class MyApplication {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(MyApplication.class, args);
    }
}


        3、定義異步任務類並使用@Component標記組件被容器掃描,異步方法加上@Async

package net.myclass.task;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

@Component
public class AsyncTask {

    @Async
    public void task1() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(1000L);
        long end = System.currentTimeMillis();
        System.out.println("任務1耗時="+(end-begin));
    }

    @Async
    public void task2() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(2000L);
        long end = System.currentTimeMillis();
        System.out.println("任務2耗時="+(end-begin));
    }

    @Async
    public void task3() throws InterruptedException{
        long begin = System.currentTimeMillis();
        Thread.sleep(3000L);
        long end = System.currentTimeMillis();
        System.out.println("任務3耗時="+(end-begin));
    }
}

           注意點:
                1)要把異步任務封裝到類裏面,不能直接寫到Controller
                2)增加Future<String> 返回結果 AsyncResult<String>("task執行完成");  
                3)如果需要拿到結果 需要判斷全部的 task.isDone()
        4、通過注入方式,注入到controller裏面,如果測試前後區別則改爲同步則把Async註釋掉

package net.myclass.controller;

import net.myclass.domain.JsonData;
import net.myclass.task.AsyncTask;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api3/async")
public class AsyncController {

    @Autowired
    private AsyncTask task;

    @GetMapping("async_task")
    public JsonData exeTask() throws InterruptedException{
        long begin=System.currentTimeMillis();
        task.task1();
        task.task2();
        task.task3();
        long end =System.currentTimeMillis();
        long total=end-begin;
        System.out.println("執行時間="+total);
        return JsonData.buildSuccess(total);
    }
}


            

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章