非同步呼叫和同步呼叫 及 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;
}
@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();
}
}
控制檯輸出如下:
相關文章
- Spring非同步Async和事務Transactional註解Spring非同步
- springboot:非同步呼叫@AsyncSpring Boot非同步
- Spring原始碼學習之:@async 方法上新增該註解實現非同步呼叫的原理Spring原始碼非同步
- async/await非同步不阻塞呼叫AI非同步
- 實戰Spring Boot 2.0系列(三) – 使用@Async進行非同步呼叫詳解Spring Boot非同步
- 實戰Spring Boot 2.0系列(三) - 使用@Async進行非同步呼叫詳解Spring Boot非同步
- spring boot(五)非同步呼叫Spring Boot非同步
- spring boot使用@Async非同步註解,原理+原始碼Spring Boot非同步原始碼
- Dubbo原始碼分析(十)同步呼叫與非同步呼叫原始碼非同步
- Spring Boot使用@Async實現非同步呼叫:自定義執行緒池Spring Boot非同步執行緒
- spring boot @Async非同步註解上下文透傳Spring Boot非同步
- Spring / Spring boot 基於註解非同步程式設計@AsyncSpring Boot非同步程式設計
- RFC 同步非同步呼叫例項非同步
- Spring中非同步註解@Async的使用、原理及使用時可能導致的問題Spring非同步
- Spring Boot使用@Async實現非同步呼叫:使用Future以及定義超時Spring Boot非同步
- Spring 3中非同步方法呼叫Spring非同步
- springboot:非同步註解@Async的前世今生Spring Boot非同步
- Java 非同步呼叫方法Java非同步
- .NET非同步方法呼叫的例子非同步
- Spring Boot使用@Async實現非同步呼叫:ThreadPoolTaskScheduler執行緒池的優雅關閉Spring Boot非同步thread執行緒
- Java實現非同步呼叫Java非同步
- 同步、非同步、阻塞和非阻塞非同步
- C#委託的非同步呼叫C#非同步
- 關於跨語言呼叫與同步非同步等的疑惑非同步
- springboot:巢狀使用非同步註解@Async還會非同步執行嗎Spring Boot巢狀非同步
- Spring Boot中如何優雅地實現非同步呼叫?Spring Boot非同步
- JavaScript非同步呼叫的發展歷程JavaScript非同步
- 短小強悍的JavaScript非同步呼叫庫JavaScript非同步
- 關於非同步介面呼叫的疑問?非同步
- 掌握C#中非同步魔法:同步方法如何優雅呼叫非同步方法C#非同步
- spring boot非同步方法@Async踩坑Spring Boot非同步
- Spring @Async開啟非同步任務Spring非同步
- springboot註解實現非同步呼叫時no bean of type TaskExecutor and no bean named 'taskExecutor' eitherSpring Boot非同步Bean
- 非同步和非阻塞非同步
- Async and Await 非同步和等待AI非同步
- Python 非同步呼叫命令列工具Python非同步命令列
- 淺談非同步呼叫幾種方式非同步
- Winform同步呼叫非同步函式死鎖原因分析、為什麼要用非同步ORM非同步函式