@async 默认线程池_SpringBoot之异步发邮件及线程池的应用

我之前直接使用 spring-boot-starter-mail 来发邮件,结果在邮件量多的时候,系统被严重拖慢,并且响应不过来,所以如果你的邮件量比较多,可以这样设计:1.单独创建一个SpringBoot的项目分布式来发送邮件。2.发送邮件时要使用异步方式,如果我们使用的是SpringBoot的@Async,底层已经帮我们解决了线程池的问题,在西方伯后面会有关于SpringBoot@Async的默认池配置:

1.maven依赖

org.springframework.boot spring-boot-starter-mail

2.配置相关配置

#mailspring.mail.host=smtp.exmail.qq.comspring.mail.username=spring.mail.password=spring.mail.properties.mail.smtp.auth=truespring.mail.properties.mail.smtp.starttls.enable=truespring.mail.properties.mail.smtp.starttls.required=truespring.mail.sendTo=

3.使用方法

@Autowired private JavaMailSender mailSender;SimpleMailMessage message = new SimpleMailMessage();message.setFrom(env.getProperty("spring.mail.username"));message.setTo(env.getProperty("spring.mail.sendTo"));message.setSubject(title);message.setText(text);mailSender.send(message);测试发现用JavaMailSender 发送也是同步,影响性能4.使用Spring的TaskExecutor实现异步发送。 @Bean public ThreadPoolTaskExecutor createThreadPoolTaskExecutor() { ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); threadPoolTaskExecutor.setCorePoolSize(10); threadPoolTaskExecutor.setMaxPoolSize(20); return threadPoolTaskExecutor; } taskExecutor.execute(() -> { try { SimpleMailMessage message = new SimpleMailMessage(); message.setFrom(env.getProperty("spring.mail.username")); message.setTo(env.getProperty("spring.mail.sendTo")); message.setSubject(title); message.setText(text); mailSender.send(message); } catch (Exception e) { logger.warn("发送邮件消息失败=exception:{}", e); } });

上面的()->的写法是 java8的Lambda写法, new Runnable()

5.使用Spring的@Async实现异步

@Async public static void AsyncMethod(){  //执行发邮件操作 }

需要启用Async , 配置一下@EnableAsync

通过@Async注解表明该方法是异步方法,如果注解在类级别上则表明该类所有的方法都是异步方法。

java原生也有线程池,有兴趣的同学可以去看看ThreadPoolExecutor类的说明

6.Main方法运行

 // 创建Properties 类用于记录邮箱的一些属性 final Properties props = new Properties(); // 表示SMTP发送邮件,必须进行身份验证 props.put("mail.smtp.auth", "true"); //此处填写SMTP服务器 props.put("mail.smtp.host", "smtp.qq.com"); //端口号,QQ邮箱给出了两个端口,但是另一个我一直使用不了,所以就给出这一个587 props.put("mail.smtp.port", "587"); // 此处填写你的账号 props.put("mail.user", "2251181679@qq.com"); // 此处的密码就是前面说的16位STMP口令 props.put("mail.password", ""); // 构建授权信息,用于进行SMTP进行身份验证 Authenticator authenticator = new Authenticator() { protected PasswordAuthentication getPasswordAuthentication() { // 用户名、密码 String userName = props.getProperty("mail.user"); String password = props.getProperty("mail.password"); return new PasswordAuthentication(userName, password); } }; // 使用环境属性和授权信息,创建邮件会话 Session mailSession = Session.getInstance(props, authenticator); // 创建邮件消息 MimeMessage message = new MimeMessage(mailSession); // 设置发件人 InternetAddress form = new InternetAddress(props.getProperty("mail.user")); message.setFrom(form); // 设置收件人的邮箱 InternetAddress[] sendTo = new InternetAddress[2]; sendTo[0] = new InternetAddress("22511181167911@qq.com"); sendTo[1] = new InternetAddress("1431081761916@qq.com"); message.setRecipients(Message.RecipientType.TO, sendTo); // 设置邮件标题 message.setSubject("测试邮件"); // 设置邮件的内容体 message.setContent("这是一封测试邮件", "text/html;charset=UTF-8"); // 最后当然就是发送邮件啦 Transport.send(message);

在SpringBoot的启用类的可以这样启动异步处理:

@ComponentScan(basePackages = { "com.xwj.controller", "com.xwj.service" })@EnableAsync //开启异步调用@EnableAutoConfigurationpublic class App { public static void main(String[] args) { SpringApplication.run(App.class, args); }}

值得注意的是,在SpringBoot中的 @Async和@Scheduled 都在底层分配了两个线程池来处理这两类的任务,我们可以这样修改@Async的默认线程池配置:

1.创建ThreadPoolConfig类,注意,需标记@EnableAsync

@Configuration@EnableAsyncpublic class ThreadPoolConfig {//其他}

2.定义defaultThreadPool

@Beanpublic Executor defaultThreadPool() {ThreadPoolTaskScheduler executor = new ThreadPoolTaskScheduler();executor.setPoolSize(线程大小);executor.setThreadPriority(优先级);executor.setThreadNamePrefix(名称前缀);executor.initialize();return executor;}

3.编写异步测试方法,注意,需标记@Async

@Asyncpublic Future async() throws InterruptedException {final long time = 5000;Thread.sleep(time);LOGGER.info("async exec");return new AsyncResult<>("job done");}

4.调用异步方法(如无需获取返回值的话,可直接调用),这里的样例是等待异步方法执行,然后获得返回值的场景

public String asyncWait() throws InterruptedException, ExecutionException {Future msg = demoService.async();final long time = 10000;while (true) {if (msg.isDone()) {break;}Thread.sleep(time);}return msg.get();}

还可以在yml配置文件里修改,比如@Scheduled默认线程池的修改:

19dbff88c7484e8eac336977bad8ce90
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值