Spring Boot入門教程(四十六): @Async
阿新 • • 發佈:2018-11-08
一:簡介
ThreadPoolTaskExecutor 用於定義執行緒池,是對java.util.concurrent.ThreadPoolExecutor類的包裝。可以通過@EnableAsync來開啟非同步支援,通過@Async來宣告一個非同步方法
二:示例
@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {
/**
* 定義執行緒池
* @return
*/
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
taskExecutor.setCorePoolSize(5);
taskExecutor.setMaxPoolSize(10);
taskExecutor.setQueueCapacity(25);
taskExecutor.initialize();
return taskExecutor;
}
/**
* 非同步方法丟擲異常時處理器
* return null: 使用預設的處理器,列印異常資訊和堆疊
* 也可以自定義自己的異常處理器
* @return
*/
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return null;
// return new MyAsyncUncaughtExceptionHandler();
}
/**
* 自定義異常處理
* 沒有返回值的非同步方法當拋異常時會走AsyncUncaughtExceptionHandler
*/
class MyAsyncUncaughtExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
System.out.println("Exception message - " + throwable.getMessage());
System.out.println("Method name - " + method.getName());
for (Object param : objects) {
System.out.println("Parameter value - " + param);
}
}
}
}
注意:非同步方法的呼叫和非同步方法的宣告必須不能在同一個類中,如果在同一個類中則變成了同步方法
@Service
public class AsyncTaskService {
/**
* 無參無返回值
*/
@Async
public void executeAsyncTask1() {
for (int i = 0; i < 5; i++) {
System.out.println("executeAsyncTask1 = " + Thread.currentThread().getName() + "\t i=" + i);
try {
Thread.sleep(100);
// int a = 1/0;
} catch (InterruptedException e) { }
}
}
/**
* 有參無返回值
* @param name
*/
@Async
public void executeAsyncTask2(String name) {
for (int i = 0; i < 5; i++) {
System.out.println(name + " =\t" + Thread.currentThread().getName() + "\t i=" + i);
try { Thread.sleep(100); } catch (InterruptedException e) { }
}
}
/**
* 有返回值有引數
* 這種情況下當方法拋異常可以在方法內部處理掉異常或者在呼叫future.get時處理異常
* @param value
* @return
*/
@Async
public Future<String> executeAsyncTask3(String value) {
Future<String> future;
try {
Thread.sleep(100);
System.out.println(value + " =\t" + Thread.currentThread().getName());
future = new AsyncResult<>(value.toUpperCase());
} catch (InterruptedException e) {
future = new AsyncResult<String>("error");
}
return future;
}
}
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringbootAsyncApplicationTests {
@Autowired
private AsyncTaskService asyncTaskService;
@Test
public void testAsync() throws Exception {
asyncTaskService.executeAsyncTask1();
asyncTaskService.executeAsyncTask2("AsyncTask2");
Future<String> future = asyncTaskService.executeAsyncTask3("AsyncTask3");
String result = future.get();
System.out.println("result=" + result);
Thread.sleep(3000);
}
@Test
public void testSync() throws Exception {
test();
for (int i = 0; i < 10; i++) {
System.out.println("testSync = " + Thread.currentThread().getName() + "\t i=" + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
}
Thread.sleep(3000);
}
/**
* 注意:@Async要想非同步,呼叫方法的程式碼和方法的宣告必須在不同的類中才能非同步,否則是同步
* test(); 方法的呼叫在SpringbootAsyncApplicationTests這個類,方法的宣告也是在這個類,所以該方法實際是同步方法,並不是非同步
*/
@Async
public void test() {
for (int i = 0; i < 10; i++) {
System.out.println("SpringbootAsyncApplicationTests = " + Thread.currentThread().getName() + "\t i=" + i);
try {
Thread.sleep(100);
} catch (InterruptedException e) { }
}
}
}