多執行緒與異步
異步是目的,而多執行緒是實作這個目的的方法,
1 Java J.U.C執行緒調度
JDK 1.5新增的java.util.concurrent包,增加了并發編程的很多類,

Executor
定義了方法execute(),用來執行一個任務
public interface Executor {
void execute(Runnable command);
}
ExecutorService
提供了生命周期管理的方法,
submit()
shutdown()
invokeAll()
invokeAny()
ThreadPoolExecutor
Java提供的執行緒池類,可自定義執行緒池大小及執行緒處理機制,
corePoolSize:執行緒池的基本大小,即在沒有任務需要執行的時候執行緒池的大小,并且只有在作業佇列滿了的情況下才會創建超出這個數量的執行緒,
maximumPoolSize:執行緒池中允許的最大執行緒數,執行緒池中的當前執行緒數目不會超過該值,
keepAliveTime:執行緒空閑時間
以poolSize表示當前執行緒數,新提交一個任務時的處理流程為:
-
如果當前執行緒池的執行緒數還沒有達到基本大小(poolSize < corePoolSize),無論是否有空閑的執行緒新增一個執行緒處理新提交的任務
-
如果當前執行緒池的執行緒數大于或等于基本大小(poolSize >= corePoolSize) 且任務佇列未滿時,就將新提交的任務提交到阻塞佇列排隊,等候處理,
-
如果當前執行緒池的執行緒數大于或等于基本大小(poolSize >= corePoolSize) 且任務佇列滿時:
- 當前poolSize<maximumPoolSize,那么就新增執行緒來處理任務
- 當前poolSize=maximumPoolSize,那么意味著執行緒池的處理能力已經達到了極限,此時需要拒絕新增加的任務,至于如何拒絕處理新增的任務,取決于執行緒池的飽和策略RejectedExecutionHandler,
ScheduledExecutorService
定時調度介面,有4種調度機制:
//帶延遲時間的調度,只執行一次,調度之后可通過Future.get()阻塞直至任務執行完畢
public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit);
//帶延遲時間的調度,只執行一次,調度之后可通過Future.get()阻塞直至任務執行完畢,并且可以獲取執行結果
public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit);
//帶延遲時間的調度,回圈執行,固定頻率
public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit);
//帶延遲時間的調度,回圈執行,固定延遲
public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit);
ScheduledThreadPoolExecutor
基于執行緒池的定時調度實作,可以用來在給定延時后執行異步任務或者周期性執行任務,
ScheduledExecutorService4種調度機制的實作,
2 Spring執行緒調度

TaskExecutor
Spring引入了TaskExecutor介面作為頂層介面,繼承至J.U.C的Executor介面,
TaskScheduler
類似于J.U.C中的ScheduledExecutorService,是任務調度的介面,
功能與ScheduledExecutorService差不多,多了一個可傳Trigger物件的schedule()方法,可支持Corn運算式進行任務調度,
ScheduledFuture<?> schedule(Runnable task, Trigger trigger);
ScheduledFuture<?> schedule(Runnable task, Date startTime);
ScheduledFuture<?> scheduleAtFixedRate(Runnable task, Date startTime, long period);
ScheduledFuture<?> scheduleAtFixedRate(Runnable task, long period);
ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
ScheduledFuture<?> scheduleWithFixedDelay(Runnable task, long delay);
AsyncTaskExecutor
介面中提供submit()方法執行任務,
ThreadPoolTaskExecutor
Spring提供的執行緒池類,與Java提供的ThreadPoolExecutor執行緒池類類似,可以配置執行緒池屬性及拒絕策略,
處理流程與ThreadPoolExecutor一樣,
ThreadPoolTaskScheduler
實作TaskScheduler介面,實作了其介面的調度機制,與Java中的ScheduledThreadPoolExecutor類類似,
多了一個可傳Trigger物件的schedule()方法,可支持Corn運算式進行任務調度,
3 Spring異步操作
使用@Async注解
標注了@Async注解的方法,稱之為異步方法,這些方法將在執行的時候,將會在獨立的執行緒(執行緒池中獲取)中被執行,呼叫者無需等待它的完成,即可繼續其他的操作,
@Configuration
@EnableAsync
public class AsyncConfig {
}
@Async
public void downloadOrder() throws InterruptedException {
System.out.println("執行開始時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("執行結束時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
}
@Async標注的方法,在同一個類中呼叫,無效
4 Spring定時任務的幾個實作
4.1 基于@Scheduled注解
@Configuration //標記為配置類
@EnableScheduling //開啟定時任務,可以放到啟動類中
public class OrderScheduler {
//定時任務執行周期,采用Corn運算式
@Scheduled(cron = "0/5 * * * * ?")
public void downloadOrder() {
System.out.println("執行開始時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("執行結束時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
}
}
//并不是每5秒執行一次,上次執行的結果會影響到下次運行,這個相當于10s運行一次了,
@Scheduled注解也可以直接指定時間間隔,如:@Scheduled(fixedRate=5000)
實作本質是基于Java中的
ScheduledExecutorService類的schedule方法,
基于@Scheduled注解默認為單執行緒的,
標注了@Scheduled的方法,執行時是單執行緒的,也就是說,上次運行的結果會影響到下一次的執行,

4.2 基于SchedulingConfigurer介面
@FunctionalInterface
public interface SchedulingConfigurer {
void configureTasks(ScheduledTaskRegistrar taskRegistrar);
}
ScheduledTaskRegistrar類
實作SchedulingConfigurer介面,實作configureTasks方法,方法傳入ScheduledTaskRegistrar類物件,
幾種定時任務型別:
- CronTask:根據Cron運算式執行定時任務
- TriggerTask:按照Trigger觸發器觸發執行,可以動態改變定時任務的執行
- FixedRateTask:固定速度執行
- FixedDelayTask:固定延遲執行
@EnableScheduling //啟動類,設定定時任務開關
@SpringBootApplication
public class MatrixApplication {
public static void main(String[] args) {
SpringApplication.run(MatrixApplication.class, args);
}
}
@Component
public class TestScheduler implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar scheduledTaskRegistrar) {
scheduledTaskRegistrar.addTriggerTask(() -> System.out.println("執行時間:" + LocalDateTime.now()), new CronTrigger("0/2 * * * * ?"));
}
}
SchedulingConfigurer配置類比@Scheduled注解多了一個TriggerTask,更加靈活,其他的差不多,
4.3 基于注解設定多執行緒定時任務
@Scheduled注解默認為單執行緒的,我們可以使用@Async注解啟用多執行緒,
@Configuration //標記為配置類
@EnableAsync //開啟多執行緒
@EnableScheduling //開啟定時任務,可以放到啟動類中
public class OrderScheduler {
//定時任務執行周期,采用Corn運算式
@Async
@Scheduled(cron = "0/5 * * * * ?")
public void downloadOrder() {
System.out.println("執行開始時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
Thread.sleep(10000);
System.out.println("執行結束時間為:" + LocalDateTime.now() + "執行緒為:" + Thread.currentThread().getName());
}
}

同一個任務的每一次定時任務執行,都會開辟一個新的執行緒,不會影響到下一次任務的執行,
4.4 ThreadPoolTaskScheduler
利用執行緒池實作任務調度,
@Resource
private ThreadPoolTaskScheduler threadPoolTaskScheduler;
@GetMapping("/start")
public void test() {
threadPoolTaskScheduler.schedule(() -> System.out.println("第" + i + "執行時間:" + LocalDateTime.now()), new CronTrigger("0/2 * * * * ?"));
}
4.5 整合Quartz
略
定時任務內部的方法可以結合@Async注解使用達到多執行緒的目的
參考文章
- https://www.cnblogs.com/frankyou/p/10135212.html
- https://blog.csdn.net/weixin_43168010/article/details/97613895
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/148118.html
標籤:Java
