1. 程式人生 > >SpringBoot 處理非同步呼叫的示例

SpringBoot 處理非同步呼叫的示例

Springboot中集成了@Async註解,我們在使用的時候直接用就好了.

 

 

不需要獲取到返回值

如果只是單純的讓執行緒去非同步執行,不需要返回結果的話,如下示例,直接進行..單執行緒進行的話,至少需要4+3+2=9秒鐘,而我們不考慮執行的結果,只是讓他去執行的話,那麼肯定在他們執行之前執行完成,

 

後來列印了一下時間,好像就用了4ms.所以,多執行緒非同步還是挺6的....

 

package com.trs.idap.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;

/**
 * Created by Administrator on 2018/10/11.
 * 描述:
 *
 * @author Young
 * @create 2018-10-11 19:48
 */
@Component
@Async
public class TestAsyncService {

    @Async
    public void execAsync1(){
        try{
            Thread.sleep(2000);
            System.out.println("甲睡了2000ms");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @Async
    public void execAsync2(){
        try{
            Thread.sleep(4000);
            System.out.println("乙睡了4000ms");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
    @Async
    public void execAsync3(){
        try{
            Thread.sleep(3000);
            System.out.println("丙睡了3000ms");
        }catch (Exception e){
            e.printStackTrace();
        }
    }
}

 

package com.trs.idap.web.rest.controller;

import com.trs.idap.service.TestAsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Created by Administrator on 2018/10/11.
 * 描述:
 * @author Young
 * @create 2018-10-11 19:46
 */
@RequestMapping("/api")
@RestController
public class TestAsync {

    @Autowired
    private TestAsyncService testAsyncService;


    @RequestMapping("execAsync")
    public void execAsync(){
        testAsyncService.execAsync1();//2s
        testAsyncService.execAsync2();//4s
        testAsyncService.execAsync3();//3s
        System.out.println("我執行結束了");
    }
}

 

 

 

需要返回值

需要返回值的情況也差不多,可以理解為,一次性把任務分發出去.然後任務各自去執行,這時分發任務後可以返回一個Future,我們可以理解為在飯店做飯給的小票,等飯好了憑小票去拿飯...

 

等我們做完其他的事情的時候,再來收集這些返回值.通過Future的get()方法,如果該Future對應的方法還沒有執行完,或者沒有結果,此時get()會阻塞在這裡,直到拿到結果值為止....

Futurn還有一個isDone()方法,只是判斷該Future對應的任務有沒有執行完成,和get()大同小異了..看你是想拿到結果,還是想看任務是否執行成功.

 

所以,我們看下,單執行緒同步的話,至少需要9s+其他處理時間,而現在是最大任務的時間+其他處理時間.此時很明顯的看清楚,9s(所有任務的時間和)是遠遠比最大任務時間要多的多....所以這就是效率....也剛起步,慢慢積累,接收批評.

 

package com.trs.idap.web.rest.controller;

import com.trs.idap.service.TestAsyncService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * Created by Administrator on 2018/10/11.
 * 描述:
 * @author Young
 * @create 2018-10-11 19:46
 */
@RequestMapping("/api")
@RestController
public class TestAsync {

    @Autowired
    private TestAsyncService testAsyncService;


    @RequestMapping("execAsync")
    public void execAsync() throws ExecutionException, InterruptedException {
        long l = System.currentTimeMillis();
        Future<String> stringFuture = testAsyncService.execAsync1();//2s
        Future<String> stringFuture1 = testAsyncService.execAsync2();//4s
        Future<String> stringFuture2 = testAsyncService.execAsync3();//3s
        //此時這裡的get方法呼叫了執行緒的阻塞,可以不用isDone進行判斷.
        //如果Future還沒有值,執行緒是阻塞的,直到獲取到值時結束
        String s = stringFuture.get();
        String s1 = stringFuture1.get();
        String s2 = stringFuture2.get();
        System.out.println("執行結束....."+s+s1+s2);
        System.out.println("我執行結束了:"+(System.currentTimeMillis()-l));
    }
}
package com.trs.idap.service;

import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;

import java.util.concurrent.Future;

/**
 * Created by Administrator on 2018/10/11.
 * 描述:
 *
 * @author Young
 * @create 2018-10-11 19:48
 */
@Component
@Async
public class TestAsyncService {

    @Async
    public Future<String> execAsync1(){
        try{
            Thread.sleep(2000);
            System.out.println("甲睡了2000ms");
            return new AsyncResult<String>("甲執行成功了");
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Async
    public Future<String> execAsync2(){
        try{
            Thread.sleep(4000);
            System.out.println("乙睡了4000ms");
            return new AsyncResult<String>("乙執行成功了");
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
    @Async
    public Future<String> execAsync3(){
        try{
            Thread.sleep(3000);
            System.out.println("丙睡了3000ms");
            return new  AsyncResult<String>("丙執行結束了");
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}