@Async實現非同步任務
阿新 • • 發佈:2022-12-12
1、@Async是SpringBoot自帶的一個執行步任務註解
@EnableAsync // 開啟非同步
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
2、同步執行
定義幾個方法,模擬耗時的操作
@Service @Slf4j public class ServiceDemoSync { public void taskOne() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務1執行結束,總耗時={" + (end - start) + "} 毫秒"); } public void taskTwo() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務2執行結束,總耗時={" + (end - start) + "} 毫秒"); } public void taskThere() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務3執行結束,總耗時={" + (end - start) + "} 毫秒"); } }
測試一下
/** * @author qbb */ @SpringBootTest public class ServiceTestSync { @Autowired private ServiceDemoSync serviceDemoSync; @Test public void test01() throws Exception { long start = System.currentTimeMillis(); serviceDemoSync.taskOne(); serviceDemoSync.taskTwo(); serviceDemoSync.taskThere(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("總任務執行結束,總耗時={" + (end - start) + "} 毫秒"); } }
3、非同步執行
@Service @Slf4j public class ServiceDemo { @Async public void taskOne() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務1執行結束,總耗時={" + (end - start) + "} 毫秒"); } @Async public void taskTwo() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務2執行結束,總耗時={" + (end - start) + "} 毫秒"); } @Async public void taskThere() throws Exception { long start = System.currentTimeMillis(); Thread.sleep(200); long end = System.currentTimeMillis(); System.out.println("執行緒:" + Thread.currentThread().getName() + "任務3執行結束,總耗時={" + (end - start) + "} 毫秒"); } }
@SpringBootTest
public class ServiceTest {
@Autowired
private ServiceDemo serviceDemo;
@Test
public void test01() throws Exception {
long start = System.currentTimeMillis();
serviceDemo.taskOne();
serviceDemo.taskTwo();
serviceDemo.taskThere();
Thread.sleep(200);
long end = System.currentTimeMillis();
System.out.println("總任務執行結束,總耗時={" + (end - start) + "} 毫秒");
}
}
4、使用自定義執行緒池
package com.qbb.service;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
/**
* 自定義執行緒池
*/
@Configuration
public class ExecutorAsyncConfig {
@Bean(name = "newAsyncExecutor")
public Executor newAsync() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
// 設定核心執行緒數
taskExecutor.setCorePoolSize(2);
// 執行緒池維護執行緒的最大數量,只有在緩衝佇列滿了以後才會申請超過核心執行緒數的執行緒
taskExecutor.setMaxPoolSize(10);
// 快取佇列
taskExecutor.setQueueCapacity(2);
// 允許的空閒時間,當超過了核心執行緒數之外的執行緒在空閒時間到達之後會被銷燬
taskExecutor.setKeepAliveSeconds(10);
// 非同步方法內部執行緒名稱
taskExecutor.setThreadNamePrefix("QIUQIU&LL-AsyncExecutor-");
// 拒絕策略
taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
taskExecutor.initialize();
return taskExecutor;
}
}
定義執行緒任務
@Component
@Slf4j
public class FutureTaskExecutor {
@Async(value = "newAsyncExecutor")
public Future<String> taskOne() {
return new AsyncResult<>(Thread.currentThread().getName() + "one 完成");
}
@Async(value = "newAsyncExecutor")
public Future<String> taskTwo() {
return new AsyncResult<>(Thread.currentThread().getName() + "two 完成");
}
@Async
public Future<String> taskThree() {
return new AsyncResult<>(Thread.currentThread().getName() + "three 完成");
}
}
測試一下
/**
* @author qbb
*/
@SpringBootTest
@Slf4j
public class FutureTaskTestExecutor {
@Autowired
private FutureTaskExecutor futureTaskExecutor;
@Test
public void runAsync() throws Exception {
long start = System.currentTimeMillis();
Future<String> taskOne = futureTaskExecutor.taskOne();
Future<String> taskTwo = futureTaskExecutor.taskTwo();
Future<String> taskThere = futureTaskExecutor.taskThree();
while (true) {
if (taskOne.isDone() && taskTwo.isDone() && taskThere.isDone()) {
System.out.println("任務1返回結果={" + (taskOne.get()) + "},任務2返回結果={" + (taskTwo.get()) + "},任務3返回結果={" + (taskThere.get()) + "}");
break;
}
}
long end = System.currentTimeMillis();
System.out.println("總任務執行結束,總耗時={" + (end - start) + "} 毫秒");
}
}
注意點:不生效的情況
1、@Async作用在static修飾的方法上不生效
2、呼叫非同步任務的方法和非同步方法在同一個類時不生效
@Service
@Slf4j
public class ServiceDemo {
@Async
public void taskOne() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(200);
long end = System.currentTimeMillis();
System.out.println("執行緒:" + Thread.currentThread().getName() + "任務1執行結束,總耗時={" + (end - start) + "} 毫秒");
}
@Async
public void taskTwo() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(200);
long end = System.currentTimeMillis();
System.out.println("執行緒:" + Thread.currentThread().getName() + "任務2執行結束,總耗時={" + (end - start) + "} 毫秒");
}
@Async
public void taskThere() throws Exception {
long start = System.currentTimeMillis();
Thread.sleep(200);
long end = System.currentTimeMillis();
System.out.println("執行緒:" + Thread.currentThread().getName() + "任務3執行結束,總耗時={" + (end - start) + "} 毫秒");
}
@Test
public void test01() throws Exception {
long start = System.currentTimeMillis();
taskOne();
taskTwo();
taskThere();
Thread.sleep(200);
long end = System.currentTimeMillis();
System.out.println("總任務執行結束,總耗時={" + (end - start) + "} 毫秒");
}
}