spring执行异步任务

1、异步任务

service层定义如下

package com.example.ascny.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service

public class AsyncService {
    public void async(){
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("正在执行异步程序!!!!");
    }
}

controller层定义如下

package com.example.ascny.controller;

import com.example.ascny.service.AsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class AsyncController {
    @Autowired
    AsyncService asyncService;
    @RequestMapping("/test")
    public String test() {
        asyncService.async(); //停止服务五分钟,一直转圈五分钟,等待服务器的响应
        return "ok";
    }
}

如果我们访问test接口,则会出现页面一直转圈五分钟,等待服务器的响应,直到五分钟后返回ok。所以为了提高用户的体验,在访问test接口的时候可以直接先给我们返回一个ok,而在后台异步执行程序!提高用户的体验感!所以我们可以使用多线程或者直接使用springboot提供的开启异步功能!
在AsyncService类中的async方法上添加 @Async注解,告诉Spring这是一个异步执行的方法。并且在项目入口类的main方法上使用@EnableAsync //开启异步支持

public class AsyncService {
    //告诉spring这是一个异步的方法
    @Async
    public void async(){
package com.example.ascny;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;

@EnableAsync   //开启异步支持
@SpringBootApplication
public class AscnyApplication {

    public static void main(String[] args) {
        SpringApplication.run(AscnyApplication.class, args);
    }

}

还有一种方法就是直接在AsyncService类中开启多线程在后台异步执行

package com.example.ascny.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class AsyncService extends Thread{
    @Override
    public void run(){
        try {
            Thread.sleep(50000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("正在执行异步程序!!!!");
    }
    public void async(){
        AsyncService asyncService = new AsyncService();
        asyncService.start();
    }
}

这样就成功地提高了用户地体验感,告诉用户后台在异步执行邮件发送等任务!你可以做自己的事情了!!!!!!

2、开启多线程的方法

(1)、 实现 Runnable 接口

package com.example.ascny;

public class mlRunnable implements Runnable{
    public static void main(String [] args){
        mlRunnable mlRunnable = new mlRunnable();
        Thread thread0 = new Thread(mlRunnable);
        Thread thread1 = new Thread(mlRunnable);
        thread0.start();
        thread1.start();
    }

    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see Thread#run()
     */
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "执行了");
    }
}


在这里插入图片描述

(2)、实现Callable接口

package com.example.ascny;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class mlCallable implements Callable<String> {
    /**
     * Computes a result, or throws an exception if unable to do so.
     *
     * @return computed result
     * @throws Exception if unable to compute a result
     */
    @Override
    public String call() throws Exception {
        return Thread.currentThread().getName()+"执行成功!!!!";
    }
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        mlCallable mc = new mlCallable();
        FutureTask<String> ft0 = new FutureTask<>(mc);
        FutureTask<String> ft1 = new FutureTask<>(mc);
        Thread thread0 = new Thread(ft0);
        Thread thread1 = new Thread(ft1);
        thread0.start();
        thread1.start();
        System.out.println(ft0.get());
        System.out.println(ft1.get());
    }
}

在这里插入图片描述

(3)、继承 Thread 类

package com.example.ascny;

public class mlThread extends Thread {
    /**
     * If this thread was constructed using a separate
     * <code>Runnable</code> run object, then that
     * <code>Runnable</code> object's <code>run</code> method is called;
     * otherwise, this method does nothing and returns.
     * <p>
     * Subclasses of <code>Thread</code> should override this method.
     *
     * @see #start()
     * @see #stop()
     */
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "执行了");
    }

    public static void main(String[] args) {
        mlThread mlThread = new mlThread();
        mlThread mlThread1 = new mlThread();
        mlThread.start();
        mlThread1.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + "执行了");
        }
    }
}

在这里插入图片描述

(4)、匿名内部类的写法

package com.example.ascny;

public class ml {
    public static void start() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "执行了");
            }
        }).start();
    }

    public static void main(String[] args) {
        start();
        start();
    }
}

在这里插入图片描述
有关线程请访问这里

3、邮件发送任务

<!--导入邮件发送的依赖包-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-mail</artifactId>
        </dependency>

因为邮件发送的依赖包是springboot家族的,导入依赖以后不需要config的配置即可使用!!!!!!!!!
application.properties中的配置如下

server.port=8001
spring.mail.username=3518806826@qq.com
#授权码
spring.mail.password=aqhnmymszxewdbfb 
spring.mail.host=smtp.qq.com
#开启加密验证
spring.mail.properties.mail.smtp.ssl.enable=true


在测试类中测试代码如下,核心是

 @Autowired
    JavaMailSenderImpl mailSender;
package com.example.ascny;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMailMessage;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.File;

@SpringBootTest
class AscnyApplicationTests {
    @Autowired
    JavaMailSenderImpl mailSender;
    @Test
    void contextLoads() {
        //一个简单的邮件
        SimpleMailMessage mailMessage = new SimpleMailMessage();
        mailMessage.setSubject("小仙女!!!!!!!!!!");
        mailMessage.setText("小仙女能看见我发的消息是吧,哈哈哈");
        mailMessage.setTo("1414492911@qq.com");
        mailMessage.setFrom("3518806826@qq.com"); //必须和spring.mail.username=3518806826@qq.com中的配置一样否则就会报错
        mailSender.send(mailMessage);
    }

    @Test
    public void sendEmail() throws MessagingException {
        //一个复杂的邮件
        MimeMessage mimeMessage = mailSender.createMimeMessage();
        //组装将要发送的消息
        MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage,true);
        messageHelper.setSubject("小仙女");
        messageHelper.setText("<p style='color:red'>我爱你,媳妇</p>",true);
        messageHelper.addAttachment("love.jpg",new File("C:\\Users\\ml\\Pictures\\love.jpg"));
        messageHelper.setTo("1414492911@qq.com");
        messageHelper.setFrom("3518806826@qq.com");  //必须和spring.mail.username=3518806826@qq.com中的配置一样否则就会报错
        mailSender.send(mimeMessage);
    }

}

当然可以将上述的方法进行封装,直接在service或者controller中调用即可

4、开启定时任务

在main函数的入口上添加@EnableScheduling //开启定时功能的注解,用于开启定时功能的注解

@SpringBootApplication
@EnableScheduling //开启定时功能的注解
public class AscnyApplication {

    public static void main(String[] args) {
        SpringApplication.run(AscnyApplication.class, args);
    }

}

service层中编写开启定时功能的代码如下

package com.example.ascny.service;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.Date;

@Service
public class ScheduledService {
    //在什么时间执行下面的脚本
    @Scheduled(cron = "0 * * * * 0-7")
    public void startScheduled(){
        SimpleDateFormat formatter= new SimpleDateFormat("yyyy-MM-dd 'at' HH:mm:ss z");
        Date date = new Date(System.currentTimeMillis());
        System.out.println("当前时间正在执行脚本"+formatter.format(date));
    }
}

其中 //在什么时间执行下面的脚本 @Scheduled(cron = "0 * * * * 0-7")用于在什么时间准时开启脚本

点击此处了解cron表达式

完结!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


版权声明:本文为qq_51691366原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。