一些参考网址:
https://www.cnblogs.com/huanzi-qch/p/11231041.html
https://www.cnblogs.com/didispace/p/15292954.html
手动使用线程执行异步方法
新建一个类继承自Runnable,实现其run方法
public class TestTask implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10000; ++i) {
Thread current = Thread.currentThread();
System.out.println("hello, world! i is " + i);
System.out.println("hello, world! current thread id is " + current.getId());
}
}
}
使用时需要new一个Thread,调用start方法执行
public static void main(String[] args) {
new Thread(new TestTask()).start();
new Thread(new TestTask()).start();
}
打印出的结果两个线程交替打印语句
也可以直接使用lambda表达式,lambda表达式参数是函数式接口,有且仅有一个抽象方法声明的接口。
public static void main(String[] args) {
new Thread(()->{
for (int i = 0; i < 10000; ++i) {
Thread current = Thread.currentThread();
System.out.println("hello, world! i is " + i);
System.out.println("hello, world! current thread id is " + current.getId());
}
}).start();
}
也可以创建实现接口的task类,放到线程池中去执行,之前总结过线程池相关:Java 线程池小结和ScheduledThreadPoolExecutor使用
使用@Async注解
在方法上加@Async注解,也可以指定线程池名字。
如果不配置线程池,使用默认线程池。见文章Spring Boot中使用@Async的时候,千万别忘了线程池的配置!
新建一个配置类
@Configuration
@EnableAsync
public class AsyncConfig {
private static final int MAX_POOL_SIZE = 50;
private static final int CORE_POOL_SIZE = 20;
@Bean("testPool")
public AsyncTaskExecutor asyncTaskExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(CORE_POOL_SIZE);
//配置最大线程数
executor.setMaxPoolSize(MAX_POOL_SIZE);
//配置队列大小
executor.setQueueCapacity(10000);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("test-pool");
// rejection-policy:当pool已经达到max size的时候,如何处理新任务
// CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
//执行初始化
executor.initialize();
return executor;
}
}
新建controller,service,service层中使用该注解
总共写了三个方法进行对比,1是不要求获取异步方法执行结果,2是直接返回异步方法结果,3是使用Future来获取结果
controller
@RestController
public class TestController {
@Resource
private AsyncService asyncService;
@GetMapping("/test/v1/api")
void testApi1() {
asyncService.dealTest1();
System.out.println("/test/v1/api");
}
@GetMapping("/test/v2/api")
Long testApi2() {
Long res = asyncService.dealTest2();
System.out.println("/test/v2/api");
return res;
}
@GetMapping("/test/v3/api")
Long testApi3() throws ExecutionException, InterruptedException {
Long aLong = asyncService.dealTest3().get();
System.out.println("/test/v3/api");
return aLong;
}
}
service
public interface AsyncService {
void dealTest1();
Long dealTest2();
Future<Long> dealTest3();
}
@Service
public class AsyncServiceImpl implements AsyncService {
@Override
@Async
public void dealTest1() {
Thread current = Thread.currentThread();
System.out.println("hello, world! current thread id is " + current.getId());
for (int i = 0; i < 10; ++i) {
System.out.println("hello, world! i is " + i);
}
}
@Override
@Async
public Long dealTest2() {
Thread current = Thread.currentThread();
System.out.println("hello, world! current thread id is " + current.getId());
for (int i = 0; i < 100000; ++i) {
System.out.println("hello, world! i is " + i);
}
return current.getId();
}
@Override
@Async
public Future<Long> dealTest3() {
Thread current = Thread.currentThread();
System.out.println("hello, world! current thread id is " + current.getId());
for (int i = 0; i < 100000; ++i) {
System.out.println("hello, world! i is " + i);
}
return AsyncResult.forValue(current.getId());
}
}
启动类
//暂时不需要连数据库
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class Demo1Application {
public static void main(String[] args) {
SpringApplication.run(Demo1Application.class, args);
}
}
结果:
- 1可以异步执行成功
- 2返回是空,异步方法没执行完,dealTest2()返回的是null
- 3.在主线程来看相当于同步方法,会等返回结果,虽然逻辑是在新线程里异步执行的