Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spring MVC异步请求Controller #185

Open
v5tech opened this issue Oct 24, 2018 · 0 comments
Open

Spring MVC异步请求Controller #185

v5tech opened this issue Oct 24, 2018 · 0 comments

Comments

@v5tech
Copy link
Owner

v5tech commented Oct 24, 2018

AsyncTaskService 模拟后台耗时请求业务

import org.joda.time.LocalDateTime;
import org.springframework.stereotype.Service;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Service
public class AsyncTaskService {

    public String uuid() {
        try {
            TimeUnit.MILLISECONDS.sleep(5000);
            System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->工作线程(" + Thread.currentThread().getName() + ")");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return UUID.randomUUID().toString();
    }

}

AsyncController 异步请求几种写法

import org.joda.time.LocalDateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.util.concurrent.ListenableFuture;
import org.springframework.util.concurrent.ListenableFutureTask;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.context.request.async.WebAsyncTask;

import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 异步Controller
 */
@RestController
@EnableAsync
public class AsyncController {

    @Autowired
    private AsyncTaskService asyncTaskService;

    /**
     * 阻塞请求
     * @return
     */
    @GetMapping("blockingRequest")
    public String blockingRequest() {

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");

        String uuid = asyncTaskService.uuid();

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");

        return uuid;

    }

    /**
     * 使用Callable
     * @return
     */
    @GetMapping("callable")
    public Callable<String> callable() {

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");

        Callable<String> callable = () -> {
            String uuid = asyncTaskService.uuid();
            System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->子任务线程("+Thread.currentThread().getName()+")");
            return uuid;
        };

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");

        return callable;

    }


    /**
     * 使用CompletableFuture
     *
     * 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题
     *
     * @return
     */
    @GetMapping("completableFuture")
    public CompletableFuture<String> completableFuture() {

        ExecutorService executor = Executors.newCachedThreadPool();

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");

        CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(asyncTaskService::uuid,executor);

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");

        return completableFuture;

    }


    /**
     * 使用ListenableFuture
     *
     * 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题
     *
     * @return
     */
    @GetMapping("listenableFuture")
    public ListenableFuture<String> listenableFuture() {

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");

        ListenableFutureTask<String> listenableFuture = new ListenableFutureTask<>(()-> asyncTaskService.uuid());

        Executors.newCachedThreadPool().execute(listenableFuture);

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");

        return listenableFuture;

    }



    /**
     * 使用WebAsyncTask
     * @return
     */
    @GetMapping("asynctask")
    public WebAsyncTask asyncTask() {

        SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始");

        WebAsyncTask<String> task = new WebAsyncTask(10000L, executor, ()-> asyncTaskService.uuid());

        task.onCompletion(()->{
            System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->调用完成");
        });

        task.onTimeout(()->{
            System.out.println("onTimeout");
            return "onTimeout";
        });


        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束");

        return task;
    }

    /**
     * 使用DeferredResult
     * @return
     */
    @GetMapping("deferredResult")
    public DeferredResult<String> deferredResult() {

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")开始");

        DeferredResult<String> deferredResult = new DeferredResult<>();

        CompletableFuture.supplyAsync(()->{

            String uuid = asyncTaskService.uuid();

            // int abc = 2/0;

            return uuid;


        }, Executors.newFixedThreadPool(5)).whenCompleteAsync((result,throwable)->{
            if (throwable!=null) {
                deferredResult.setErrorResult(throwable.getMessage());
            }else {
                deferredResult.setResult(result);
            }
        });


        // 异步请求超时时调用
        deferredResult.onTimeout(()->{
            System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onTimeout");
        });

        // 异步请求完成后调用
        deferredResult.onCompletion(()->{
            System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onCompletion");
        });

        System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")结束");

        return deferredResult;
    }

}

参考文档

https://www.javacodegeeks.com/2015/07/understanding-callable-and-spring-deferredresult.html

https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant