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,正在解析......"; } }