spring使用@Async注解异步处理
1. 何為異步調(diào)用?
在解釋異步調(diào)用之前,我們先來看同步調(diào)用的定義;同步就是整個處理過程順序執(zhí)行,當(dāng)各個過程都執(zhí)行完畢,并返回結(jié)果。 異步調(diào)用則是只是發(fā)送了調(diào)用的指令,調(diào)用者無需等待被調(diào)用的方法完全執(zhí)行完畢;而是繼續(xù)執(zhí)行下面的流程。例如, 在某個調(diào)用中,需要順序調(diào)用 A, B, C三個過程方法;如他們都是同步調(diào)用,則需要將他們都順序執(zhí)行完畢之后,方算作過程執(zhí)行完畢; 如B為一個異步的調(diào)用方法,則在執(zhí)行完A之后,調(diào)用B,并不等待B完成,而是執(zhí)行開始調(diào)用C,待C執(zhí)行完畢之后,就意味著這個過程執(zhí)行完畢了。
2. 常規(guī)的異步調(diào)用處理方式
在Java中,一般在處理類似的場景之時,都是基于創(chuàng)建獨立的線程去完成相應(yīng)的異步調(diào)用邏輯,通過主線程和不同的線程之間的執(zhí)行流程,從而在啟動獨立的線程之后,主線程繼續(xù)執(zhí)行而不會產(chǎn)生停滯等待的情況。
3. @Async介紹
在Spring中,基于@Async標(biāo)注的方法,稱之為異步方法;這些方法將在執(zhí)行的時候,將會在獨立的線程中被執(zhí)行,調(diào)用者無需等待它的完成,即可繼續(xù)其他的操作。
分為不帶參數(shù)的異步調(diào)用;帶參數(shù)的異步調(diào)用;調(diào)用返回Future的異步線程
4. @Async調(diào)用中的事務(wù)處理機(jī)制
在@Async標(biāo)注的方法,同時也適用了@Transactional進(jìn)行了標(biāo)注;在其調(diào)用數(shù)據(jù)庫操作之時,將無法產(chǎn)生事務(wù)管理的控制,原因就在于其是基于異步處理的操作。 那該如何給這些操作添加事務(wù)管理呢?可以將需要事務(wù)管理操作的方法放置到異步方法內(nèi)部,在內(nèi)部被調(diào)用的方法上添加@Transactional. 例如: 方法A,使用了@Async/@Transactional來標(biāo)注,但是無法產(chǎn)生事務(wù)控制的目的。 方法B,使用了@Async來標(biāo)注, B中調(diào)用了C、D,C/D分別使用@Transactional做了標(biāo)注,則可實現(xiàn)事務(wù)控制的目的。
5. 配合使用@EnableAsync
@EnableAsync
在啟動類或者Control類加上 @EnableAsync 注解
@EnableAsync注解的意思是可以異步執(zhí)行,就是開啟多線程的意思。可以標(biāo)注在方法、類上。@Async所修飾的函數(shù)不要定義為static類型,這樣異步調(diào)用不會生效
如下:
@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數(shù)據(jù)時候用同步,插入order_table用異步。
在controller類中創(chuàng)建一個方法 同時保存user_info和order_table表。保存order_table用異步(對應(yīng)service方法中用@Async標(biāo)注)
(1)domain文件夾中創(chuàng)建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)創(chuàng)建repository層操作數(shù)據(jù)庫。如果是普通保存方法,只需要接口繼承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的實現(xiàn)層保存方法加上@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 輸入對應(yīng)鍵值對* @param name* @param age* @return*/@PostMapping(value = "/save-one") //相當(dāng)于@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
總結(jié)
以上是生活随笔為你收集整理的spring使用@Async注解异步处理的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Redis【入门】就这一篇!
- 下一篇: 《Effective-Ruby》读书笔记