1. 方法的同步
同步處理
這種同步的方式處理,會發現,當這100此循環完成后,頁面才會返回 :同步,正在解析......。
當后台在循環處理時,前台的頁面始終處於等待狀態。可以發現,使用都是一個線程在處理:
1.1 service
/** * 同步方法 */ public void getTest1() { Users users = new Users(); synchronized (users) { try { for (int i = 1; i <= 100; i++) { log.info(Thread.currentThread().getName() + "----------同步:>" + i); users.wait(200); } } catch (Exception ex) { ex.printStackTrace(); } } }
1.2 controller
/** * 同步處理 * 這種同步的方式處理,會發現,當這100此循環完成后,頁面才會返回 :同步,正在解析......。 * 當后台在循環處理時,前台的頁面始終處於等待狀態。可以發現,使用都是一個線程在處理: * @return */ @RequestMapping(value = "test1") public String test1(){ loginService.getTest1(); log.info(Thread.currentThread().getName()+"==========主線程名"); return "同步,正在解析......"; }
2. 方法的異步
2.1 異步處理1:
實現:線程池,創建新線程處理
我們看控制台,會發現,主線程,和處理任務的線程,不是一個線程,也就是,當頁面請求后,主線程會返回我們想要返回的標識,
這里返回的是一個字符串:異步,正在解析......,而線程池新開了一個線程,在后台處理業務邏輯。
所以,此時訪問接口后,會立馬返回,頁面不用等待,處理邏輯在后台默默進行。
2.1.1 創建線程
package com.synchronize.RunnableTask; import com.synchronize.model.Users; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class RunnableTask1 implements Runnable{ private final Logger logger = LoggerFactory.getLogger(getClass()); @Override public void run(){ Users users = new Users(); synchronized (users){ try { for (int i = 1;i <= 100;i++){ System.out.println(Thread.currentThread().getName()+"----------異步1:>"+i); users.wait(200); } }catch (Exception ex){ ex.printStackTrace(); } } } }
2.1.2 controller
/** * 異步處理1:線程池,創建新線程處理 * 我們看控制台,會發現,主線程,和處理任務的線程,不是一個線程,也就是,當頁面請求后,主線程會返回我們想要返回的標識, * 這里返回的是一個字符串:異步,正在解析......,而線程池新開了一個線程,在后台處理業務邏輯。 * 所以,此時訪問接口后,會立馬返回,頁面不用等待,處理邏輯在后台默默進行。 * @return */ @RequestMapping(value = "test2") public String test2(){ ExecutorService service = Executors.newFixedThreadPool(5); RunnableTask1 task1 = new RunnableTask1(); service.execute(task1); log.info("=========》當前線程名:"+Thread.currentThread().getName()); return "異步1,正在解析......"; }
2.2 異步處理2:
實現:用springBoot自帶async注解
這種方式,是springBoot自身的一種異步方式,使用注解實現,非常方便,
我們在想要異步執行的方法上加上@Async注解,在controller上加上@EnableAsync,即可。
注意,這里的異步方法,只能在自身之外調用,在本類調用是無效的。
2.2.1 service
/**異步方法 * 有@Async注解的方法,默認就是異步執行的,會在默認的線程池中執行,但是此方法不能在本類調用; * 啟動類需添加直接開啟異步執行@EnableAsync。 * */ @Async public String getTest2(){ Users users = new Users(); synchronized (users){ try { for (int i = 1;i <= 100;i++){ log.info(Thread.currentThread().getName()+"----------異步2:>"+i); users.wait(200); } return "執行異步任務完畢"; }catch (Exception ex){ ex.printStackTrace(); } } return Thread.currentThread().getName()+"執行完畢"; }
2.2.2 controller
package com.synchronize.controller; import com.synchronize.RunnableTask.RunnableTask1; import com.synchronize.service.LoginService; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * @author luoxianwei * @date 2018/6/12 */ @RestController @Slf4j @EnableAsync public class SynchronizedMethodController { @Autowired LoginService loginService; /** * 異步處理2:使用springBoot自帶async注解 * 這種方式,是springBoot自身的一種異步方式,使用注解實現,非常方便, * 我們在想要異步執行的方法上加上@Async注解,在controller上加上@EnableAsync,即可。 * 注意,這里的異步方法,只能在自身之外調用,在本類調用是無效的。 */ @RequestMapping(value = "test3") public String test3(){ loginService.getTest2(); log.info("============>"+Thread.currentThread().getName()); return "異步2,正在解析......"; } }