Spring Boot實戰|異步調用

《JavaEE開發的顛覆者: Spring Boot實戰》系列讀書筆記

Spring boot異步調用@Async


什麼是異步調用?

  • 異步調用是相對於同步調用而言的,同步調用是指程序按預定順序一步步執行,每一步必須等到上一步執行完後才能執行,異步調用則無需等待上一步程序執行完即可執行。

如何實現異步調用?

  • 多線程是一種實現異步調用的方式,在非spring目項目中我們要實現異步調用的就是使用多線程方式,可以自己實現Runable接口或者集成Thread類,或者使用Executors線程池。

    SpringBoot中則提供了很方便的方式執行異步調用,一個@Async就可搞定。

開始使用

  • 在啓動類上加上@EnableAsync註解開啓異步

controller層

  • 寫一個同步接口和異步接口,在需要異步的執行方法上添加@Async註解

    @RequestMapping("async")
    @RestController
    public class AsyncTaskController {
    	
    	@Autowired
    	private AsyncTask asyncTask;
    
    	@RequestMapping(value = "doTask",method = RequestMethod.GET)
    	public String doTask() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		asyncTask.task1();
    		asyncTask.task2();
    		asyncTask.task3();
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("異步任務總耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    		return "success";
    		
    	}
    	@RequestMapping("justDo")
    	public String justDo() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		task1();
    		task2();
    		task3();
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務總耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    		return "success";
    
    	}
    
    	@RequestMapping("doTaskSuccess")
    	public String doTaskSuccess() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Future<String> task1 = asyncTask.task1s();
    		Future<String> task2 = asyncTask.task2s();
    		Future<String> task3 = asyncTask.task3s();
    		String result = null;
    		for (;;) {
    			if(task1.isDone() && task2.isDone() && task3.isDone()) {
    				// 三個任務都調用完成,退出循環等待
    				break;
    			}
    			//Thread.sleep(1000);
    		}
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("異步任務總耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    		return "success";
    	}
    
    	public String threadAsynchSayHello() {
    		Runnable runnable = ()-> {
    			try {
    				long currentTimeMillis = System.currentTimeMillis();
    				Thread.sleep(1000);
    				long currentTimeMillis1 = System.currentTimeMillis();
    				System.out.println("任務三耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    			} catch (InterruptedException e) {
    				e.printStackTrace();
    			}
    		};
    		System.out.println(Thread.currentThread().getName()+"  開啓新線程");
    		new Thread(runnable).start();
    		return "success";
    	}
    
    
    	public void task1() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務一耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    
    	public void task2() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務二耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    	public void task3() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務三耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    }
    

異步任務類

  • 將異步任務單獨放到一個類中

    @Component
    public class AsyncTask {
    
    	/**
    	 * 異步-無返回值
    	 * @throws InterruptedException
    	 */
    	@Async
    	public void task1() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務一耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    	
    	@Async
    	public void task2() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務二耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    	@Async
    	public void task3() throws InterruptedException{
    		long currentTimeMillis = System.currentTimeMillis();
    		Thread.sleep(1000);
    		long currentTimeMillis1 = System.currentTimeMillis();
    		System.out.println("任務三耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
    	}
    }
    
  • 如何知道異步任務什麼時候執行完,執行的結果怎樣呢?可以採用添加Fature回調方式判斷

    /**
        	 * 異步-  future回調方式
        	 * @return
        	 * @throws InterruptedException
        	 */
        	@Async
        	public Future<String> task1s() throws InterruptedException{
        		long currentTimeMillis = System.currentTimeMillis();
        		Thread.sleep(1000);
        		long currentTimeMillis1 = System.currentTimeMillis();
        		System.out.println("任務一耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        		return new AsyncResult<String>("任務一執行完畢");
        	}
        
        	@Async
        	public Future<String> task2s() throws InterruptedException{
        		long currentTimeMillis = System.currentTimeMillis();
        		Thread.sleep(2000);
        		long currentTimeMillis1 = System.currentTimeMillis();
        		System.out.println("任務二耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        		return new AsyncResult<String>("任務二執行完畢");
        	}
        	@Async
        	public Future<String> task3s() throws InterruptedException{
        		long currentTimeMillis = System.currentTimeMillis();
        		Thread.sleep(3000);
        		long currentTimeMillis1 = System.currentTimeMillis();
        		System.out.println("任務三耗時:"+(currentTimeMillis1-currentTimeMillis)+"ms");
        		return new AsyncResult<String>("任務三執行完畢");
        	}
    

用postman進行測試:
執行異步:
執行異步
同步執行:
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章