1. 何爲異步調用?
在解釋異步調用以前,咱們先來看同步調用的定義;同步就是整個處理過程順序執行,當各個過程都執行完畢,並返回結果。 異步調用則是隻是發送了調用的指令,調用者無需等待被調用的方法徹底執行完畢;而是繼續執行下面的流程。例如, 在某個調用中,須要順序調用 A, B, C三個過程方法;如他們都是同步調用,則須要將他們都順序執行完畢以後,方算做過程執行完畢; 如B爲一個異步的調用方法,則在執行完A以後,調用B,並不等待B完成,而是執行開始調用C,待C執行完畢以後,就意味着這個過程執行完畢了。
2. 常規的異步調用處理方式
在Java中,通常在處理相似的場景之時,都是基於建立獨立的線程去完成相應的異步調用邏輯,經過主線程和不一樣的線程之間的執行流程,從而在啓動獨立的線程以後,主線程繼續執行而不會產生停滯等待的狀況。
3. @Async介紹
在Spring中,基於@Async標註的方法,稱之爲異步方法;這些方法將在執行的時候,將會在獨立的線程中被執行,調用者無需等待它的完成,便可繼續其餘的操做。
分爲不帶參數的異步調用;帶參數的異步調用;調用返回Future的異步線程
4. @Async調用中的事務處理機制
在@Async標註的方法,同時也適用了@Transactional進行了標註;在其調用數據庫操做之時,將沒法產生事務管理的控制,緣由就在於其是基於異步處理的操做。 那該如何給這些操做添加事務管理呢?能夠將須要事務管理操做的方法放置到異步方法內部,在內部被調用的方法上添加@Transactional. 例如: 方法A,使用了@Async/@Transactional來標註,可是沒法產生事務控制的目的。 方法B,使用了@Async來標註, B中調用了C、D,C/D分別使用@Transactional作了標註,則可實現事務控制的目的。html
5. 配合使用@EnableAsyncjava
@EnableAsync
在啓動類或者Control類加上 @EnableAsync 註解web
@EnableAsync註解的意思是能夠異步執行,就是開啓多線程的意思。能夠標註在方法、類上。@Async所修飾的函數不要定義爲static類型,這樣異步調用不會生效spring
以下:數據庫
@SpringBootApplication
@EnableAsync
public class Application
{
public static void main( String[] args )
{
SpringApplication.run(Application.class, args);
}
}segmentfault
或者:多線程
@EnableAsync
@RestController
public class HelloController {
@Autowired
TestAsyncService testAsyncService;app
}dom
6. 舉例:異步
兩張表:user_info和order_table 插入user_info數據時候用同步,插入order_table用異步。
在controller類中建立一個方法 同時保存user_info和order_table表。保存order_table用異步(對應service方法中用@Async標註)
(1)domain文件夾中建立Entity類
package com.cfj.ceshi.async.domain; import java.io.Serializable; import java.util.Date; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="order_table") public class OrderTable implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; @Column(name = "order_name") private String orderName; @Column(name = "user_id") private Integer userId; @Column(name = "create_date") private Date createDate; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getOrderName() { return orderName; } public void setOrderName(String orderName) { this.orderName = orderName; } public Integer getUserId() { return userId; } public void setUserId(Integer userId) { this.userId = userId; } public Date getCreateDate() { return createDate; } public void setCreateDate(Date createDate) { this.createDate = createDate; } }
package com.cfj.ceshi.async.domain; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="user_info") public class UserInfo implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Integer id; private String userName; private String age; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName = userName; } public String getAge() { return age; } public void setAge(String age) { this.age = age; } @Override public String toString() { return "UserInfo [id=" + id + ", userName=" + userName + ", age=" + age + "]"; } }
(2)建立repository層操做數據庫。若是是普通保存方法,只須要接口繼承JpaRepository,不須要寫具體方法
package com.cfj.ceshi.async.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.cfj.ceshi.async.domain.OrderTable; public interface OrderRepository extends JpaRepository<OrderTable, Integer> { }
package com.cfj.ceshi.async.repository; import org.springframework.data.jpa.repository.JpaRepository; import com.cfj.ceshi.async.domain.UserInfo; public interface UserRepository extends JpaRepository<UserInfo, Integer> { }
(3)service層 其中order的實現層保存方法加上@Async
package com.cfj.ceshi.async.service; public interface OrderService { public void saveOrder(Integer UserId,String name); }
package com.cfj.ceshi.async.service; import java.util.List; import com.cfj.ceshi.async.domain.UserInfo; public interface UserService { public Integer save(UserInfo user); }
package com.cfj.ceshi.async.service.impl; import java.util.Date; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import com.cfj.ceshi.async.domain.OrderTable; import com.cfj.ceshi.async.repository.OrderRepository; import com.cfj.ceshi.async.service.OrderService; @Service public class OrderServiceImpl implements OrderService { @Autowired OrderRepository orderRepository; /** * 異步保存 */ @Async @Override public void saveOrder(Integer UserId,String name) { System.out.println("UserId:"+UserId); System.out.println("=====" + Thread.currentThread().getName() + "========="); OrderTable orderTable = new OrderTable(); orderTable.setOrderName(name+"訂單"); orderTable.setUserId(UserId); orderTable.setCreateDate(new Date()); orderRepository.save(orderTable); } }
package com.cfj.ceshi.async.service.impl; import java.util.List; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.cfj.ceshi.async.domain.UserInfo; import com.cfj.ceshi.async.repository.UserRepository; import com.cfj.ceshi.async.service.UserService; @Service @Transactional public class UserServiceImpl implements UserService{ @Autowired private UserRepository userRepository; @Override public Integer save(UserInfo user) { System.out.println("=====" + Thread.currentThread().getName() + "========="); return userRepository.save(user).getId(); } }
(4) control層,control類中添加@EnableAsync註解
package com.cfj.ceshi.async.web; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.cfj.ceshi.async.domain.UserInfo; import com.cfj.ceshi.async.service.OrderService; import com.cfj.ceshi.async.service.UserService; @EnableAsync @RestController @RequestMapping("/tesasyc") public class AsycWeb { @Autowired UserService userService; @Autowired OrderService orderService; /** * 請使用 postman測試 方式選擇post http://localhost:8081/tesasyc/save-one * body 中選擇form-data 或者x-wwww-form-urlencoded 輸入對應鍵值對 * @param name * @param age * @return */ @PostMapping(value = "/save-one") //至關於@RequestMapping(value = "/save-one", method = RequestMethod.POST) public String postOne(String name,String age) { UserInfo user = new UserInfo(); user.setUserName(name); user.setAge(age); Integer id = userService.save(user); orderService.saveOrder(id,name); return id.toString(); } }
參考:https://www.cnblogs.com/memoryXudy/p/7737418.htmlhttps://segmentfault.com/a/1190000013974727https://www.cnblogs.com/andyfengzp/p/6824253.htmlhttps://www.cnblogs.com/benefitworld/p/5877423.html