异步的八种实现方式
package com.example;public class AsyncThread extends Thread {@Overridepublic void run() {System.out.println("current thread name " + Thread.currentThread().getName());}public static void main(String[] args) {AsyncThread asyncThread = new AsyncThread();asyncThread.start();// current thread name Thread-0}
}
使用线程池
package com.example;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class AsyncThread extends Thread {// 线程池private static ExecutorService executorService = Executors.newCachedThreadPool();@Overridepublic void run() {System.out.println("current thread name " + Thread.currentThread().getName());}public static void main(String[] args) {executorService.submit(new AsyncThread());// current thread name pool-1-thread-1// 进程卡住,没有结束}
}
可以获取执行结果
package com.example;import java.util.concurrent.*;public class FutureTask {public static void main(String[] args) throws ExecutionException, InterruptedException {ExecutorService executorService = Executors.newFixedThreadPool(1);Future future = executorService.submit(new Callable() {@Overridepublic String call() throws Exception {System.out.println("start");Thread.sleep(3000);System.out.println("end");return "success";}});// 等待任务结束,获取返回值String result = future.get();System.out.println(result);}
}
package com.example;import java.util.concurrent.*;public class AsyncTask {public static void main(String[] args) throws ExecutionException, InterruptedException {CompletableFuture result1 = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName());return "success";});CompletableFuture result2 = result1.thenRunAsync(() -> {System.out.println(Thread.currentThread().getName());});System.out.println(result1.get());System.out.println(result2.get());// 输出结果// ForkJoinPool.commonPool-worker-1// success// ForkJoinPool.commonPool-worker-1// null}
}
推荐自定义线程池实现异步
项目结构
$ tree
.
├── pom.xml
└── src└── main├── java│ └── com│ └── example│ └── demo│ ├── Application.java│ ├── config│ │ └── TaskPoolConfig.java│ ├── controller│ │ └── IndexController.java│ └── service│ ├── AsyncService.java│ └── impl│ └── AsyncServiceImpl.java└── resources├── application.yml├── static└── templates
pom.xml依赖
4.0.0 org.springframework.boot spring-boot-starter-parent 2.7.7 com.example demo 0.0.1-SNAPSHOT demo Demo project for Spring Boot 1.8 org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-devtools runtime true org.projectlombok lombok true org.springframework.boot spring-boot-starter-test test org.springframework.boot spring-boot-maven-plugin org.projectlombok lombok
TaskPoolConfig.java
package com.example.demo.config;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;/*** 线程池参数配置**/
@EnableAsync
@Configuration
public class TaskPoolConfig {/*** 自定义线程池**/@Beanpublic Executor taskExecutor() {//返回可用处理器的Java虚拟机的数量 12int i = Runtime.getRuntime().availableProcessors();System.out.println("系统最大线程数 : " + i);ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();//核心线程池大小executor.setCorePoolSize(16);//最大线程数executor.setMaxPoolSize(20);//配置队列容量,默认值为Integer.MAX_VALUEexecutor.setQueueCapacity(99999);//活跃时间executor.setKeepAliveSeconds(60);//线程名字前缀executor.setThreadNamePrefix("asyncServiceExecutor -");//设置此执行程序应该在关闭时阻止的最大秒数,以便在容器的其余部分继续关闭之前等待剩余的任务完成他们的执行executor.setAwaitTerminationSeconds(60);//等待所有的任务结束后再关闭线程池executor.setWaitForTasksToCompleteOnShutdown(true);return executor;}
}
AsyncService.java
package com.example.demo.service;public interface AsyncService {void sendEmail();
}
AsyncServiceImpl.java
package com.example.demo.service.impl;import com.example.demo.service.AsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class AsyncServiceImpl implements AsyncService {@Async@Overridepublic void sendEmail() {try {// 模拟耗时3秒Thread.sleep(3 * 1000);} catch (Exception e) {System.out.println("Email发送异常");}System.out.println("Email发送成功");}
}
IndexController.java
package com.example.demo.controller;import com.example.demo.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IndexController {@Autowiredprivate AsyncService asyncService;@GetMapping("/")public String index(){asyncService.sendEmail();return "success";}
}
Application.java
package com.example.demo;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}
基于上一节的异步配置,实现异步事件
$ tree
.
├── pom.xml
└── src└── main├── java│ └── com│ └── example│ └── demo│ ├── Application.java│ ├── config│ │ └── TaskPoolConfig.java│ ├── controller│ │ └── IndexController.java│ ├── entity│ │ └── User.java│ ├── event│ │ └── AsyncSendEmailEvent.java│ └── listener│ └── AsyncSendEmailListener.java└── resources├── application.yml├── static└── templates
User.java
package com.example.demo.entity;import lombok.Data;@Data
public class User {private Integer age;private String name;
}
AsyncSendEmailEvent.java
package com.example.demo.event;import com.example.demo.entity.User;
import org.springframework.context.ApplicationEvent;/*** 自定义事件*/
public class AsyncSendEmailEvent extends ApplicationEvent {private User user;public AsyncSendEmailEvent(User user) {super(user);this.user = user;}public User getUser() {return this.user;}
}
AsyncSendEmailListener.java
package com.example.demo.listener;import com.example.demo.event.AsyncSendEmailEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;/*** 事件监听器*/
@Component
public class AsyncSendEmailListener implements ApplicationListener {@Async@Overridepublic void onApplicationEvent(AsyncSendEmailEvent event) {System.out.println(event.getUser());try {Thread.sleep(3 * 1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("邮件发送成功");}
}
IndexController.java
package com.example.demo.controller;import com.example.demo.entity.User;
import com.example.demo.event.AsyncSendEmailEvent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class IndexController {@Autowiredprivate ApplicationEventPublisher publisher;@GetMapping("/")public String index() {User user = new User();user.setName("Tom");user.setAge(20);// 发布事件publisher.publishEvent(new AsyncSendEmailEvent(user));return "success";}
}