spring使用@Async注解异步处理
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做了標注,則可實現事務控制的目的。
5. 配合使用@EnableAsync
@EnableAsync
在啟動類或者Control類加上 @EnableAsync 注解
@EnableAsync注解的意思是可以異步執行,就是開啟多線程的意思??梢詷俗⒃诜椒?、類上。@Async所修飾的函數不要定義為static類型,這樣異步調用不會生效
如下:
@SpringBootApplication
@EnableAsync
public class Application
{
??? public static void main( String[] args )
??? {
?? ??? ?SpringApplication.run(Application.class, args);
??? }
}
或者:
@EnableAsync
@RestController
public class HelloController {
?? ?
?? ?@Autowired
?? ?TestAsyncService testAsyncService;
}
?
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;}@Overridepublic 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 {@AutowiredOrderRepository orderRepository;/*** 異步保存*/@Async@Overridepublic 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{@Autowiredprivate UserRepository userRepository;@Overridepublic 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 {@AutowiredUserService userService;@AutowiredOrderService 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.html
https://segmentfault.com/a/1190000013974727
https://www.cnblogs.com/andyfengzp/p/6824253.html
https://www.cnblogs.com/benefitworld/p/5877423.html
總結
以上是生活随笔為你收集整理的spring使用@Async注解异步处理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis【入门】就这一篇!
- 下一篇: 《Effective-Ruby》读书笔记