1、创建线程池
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@EnableAsync
@Configuration
public class ExecturConfig {
@Bean("taskExecutor")
public Executor taskExector() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(100);
executor.setKeepAliveSeconds(50);
executor.setQueueCapacity(50000);
executor.setThreadNamePrefix("");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setWaitForTasksToCompleteOnShutdown(true);
executor.initialize();
return executor;
}
}
2、业务方法添加 @Async 注解
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@Service
public class TestServiceImpl {
public static volatile AtomicInteger i = new AtomicInteger(0);
@Async("taskExecutor")
public void test() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("当前第" + i.incrementAndGet() + "次执行");
}
@Async("taskExecutor")
public Future<String> test2() {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult("当前第" + i.incrementAndGet() + "次执行");
}
}
3、测试
import com.meiya.engineScheduling.config.TestServiceImpl;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class ApplicationTest {
@Autowired
private TestServiceImpl testServiceImpl;
@Test
public void test() {
TestServiceImpl.i = new AtomicInteger(0);
for (int i = 0; i < 20; i++) {
System.out.println("第" + (i + 1) + "个任务加入队列");
testServiceImpl.test();
}
System.out.println("已全部加入队列");
}
@Test
public void test2() throws InterruptedException, ExecutionException {
TestServiceImpl.i = new AtomicInteger(0);
for (int i = 0; i < 20; i++) {
System.out.println("第" + (i + 1) + "个任务加入队列");
Future<String> future = testServiceImpl.test2();
System.out.println(future.get());
}
System.out.println("已全部加入队列");
}
}
4、注解失效原因
1. 注解的方法必须是 public 方法
2. 方法一定要从另一个类中调用,也就是从类的外部调用,类的内部调用是无效的。
因为 @Async 注解的实现都是基于 AOP 动态代理,所以内部调用失效的原因是由于调用方法的是对象本身而不是代理对象,没有经过 Spring 容器
3. 异步方法使用注解 @Async 的返回值只能为 void 或者 Future