Spring中@Async註解實現「方法」的異步調用

簡單介紹
Spring爲任務調度與異步方法執行提供了註解支持。經過在方法上設置@Async註解,可以使得方法被異步調用。也就是說調用者會在調用時當即返回,而被調用方法的實際執行是交給Spring的TaskExecutor來完成。java

 

同時加入掃描註解。網絡

爲了比較,先來一個同步調用app

@Component
public class TestAsyncBean {
public void sayHello4() throws InterruptedException {
Thread.sleep(2 * 1000);//網絡鏈接中 。。。消息發送中。。。
System.out.println("我愛你啊!");
}
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Test
public void test_sayHello4() throws InterruptedException, ExecutionException {
System.out.println("你不愛我了麼?");
testAsyncBean.sayHello4();
System.out.println("回的這麼慢, 你確定不愛我了, 咱們仍是分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進程過早結束
}
}

 

輸出結果:異步

你不愛我了麼?
我愛你啊!
回的這麼慢, 你確定不愛我了, 咱們仍是分手吧。。。

同步調用會按代碼順序依次進行下去,若是哪裏須要等待,那麼就阻塞在那裏,再也不向下繼續進行。spa

使用@Async的異步調用:線程

@Component
public class TestAsyncBean {
@Async
public void sayHello3() throws InterruptedException {
Thread.sleep(2 * 1000);//網絡鏈接中 。。。消息發送中。。。
System.out.println("我愛你啊!");
}
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello3() throws InterruptedException, ExecutionException {
System.out.println("你不愛我了麼?");
testAsyncBean.sayHello3();
System.out.println("你竟無話可說, 咱們分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進程過早結束
}
}

  

輸出結果:code

你不愛我了麼?
你竟無話可說, 咱們分手吧。。。
我愛你啊!

異步調用,經過開啓新的線程來執行調用的方法,不影響主線程。異步方法實際的執行交給了Spring的TaskExecutor來完成。xml

上面這種方式是沒有返回值的,下面嘗試有返回值的異步調用:blog

@Component
public class TestAsyncBean {
@Async
public String sayHello2() throws InterruptedException {
Thread.sleep(2 * 1000);//網絡鏈接中 。。。消息發送中。。。
return "我愛你啊!";// 調用方調用後會當即返回,因此返回null
}
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello2() throws InterruptedException, ExecutionException {
System.out.println("你不愛我了麼?");
System.out.println(testAsyncBean.sayHello2());
System.out.println("你說的啥? 咱們仍是分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進程過早結束
}
}

輸出結果進程

輸出結你不愛我了麼?
null
你說的啥? 咱們仍是分手吧。。。

接獲取返回值得方式是不行的,這裏就須要用到異步回調,異步方法返回值必須爲Future<>,就像Callable與Future。

下面經過AsyncResult<>來得到異步調用的返回值:

@Component
public class TestAsyncBean {
@Async
public Future<String> sayHello1() throws InterruptedException {
int thinking = 2;
Thread.sleep(thinking * 1000);//網絡鏈接中 。。。消息發送中。。。
System.out.println("我愛你啊!");
return new AsyncResult<String>("發送消息用了"+thinking+"秒");
}
}

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"classpath:/applicationContext.xml"})
public class TestAsync {
@Autowired
private TestAsyncBean testAsyncBean;
@Test
public void test_sayHello1() throws InterruptedException, ExecutionException {
Future<String> future = null;
System.out.println("你不愛我了麼?");
future = testAsyncBean.sayHello1();
System.out.println("你竟無話可說, 咱們分手吧。。。");
Thread.sleep(3 * 1000);// 不讓主進程過早結束
System.out.println(future.get());
}
}

輸出結果:

你不愛我了麼?你竟無話可說, 咱們分手吧。。。我愛你啊!發送消息用了2秒

相關文章
相關標籤/搜索