一、异步与同步
- 异步调用:程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序;
- 同步调用:程序按照定义顺序依次执行,每行代码必须等待上一行程序执行完才能执行;
下面我们通过代码详细比较同步与异步的差异
同步调用
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Random;
/**
* 同步信息
*
* @author <a href="jian.huang@bintools.cn">yunzhe</a>
* @version 1.0.0 2019-07-09-下午8:45
*/
@Component
@Slf4j
public class SyncTask {
public static Random random = new Random();
public void doTaskOne() throws InterruptedException {
log.info("sync开始任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("sync完成任务一、耗时:"+(end-start)+"毫秒");
}
public void doTaskTwo() throws InterruptedException {
log.info("sync开始任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("sync完成任务二、耗时:"+(end-start)+"毫秒");
}
public void doTaskThree() throws InterruptedException {
log.info("sync开始任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("sync完成任务三、耗时:"+(end-start)+"毫秒");
}
}
执行结果;
syncTask.jpg异步处理
- 1 创建连接池
/***
* 创建线程池
*/
@EnableAsync
@Configuration
class TaskPoolConfig{
@Bean("taskExecutor")
public Executor taskExecutor(){
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(200);
executor.setKeepAliveSeconds(60);
executor.setThreadNamePrefix("taskExecutor-");
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
}
- 2 异步处理
import java.util.Random;
/**
* 异步处理
*
* @author <a href="jian.huang@bintools.cn">yunzhe</a>
* @version 1.0.0 2019-07-09-上午11:19
*/
@Slf4j
@Component
public class Task {
public static Random random = new Random();
@Async("taskExecutor")
public void doTaskOne() throws InterruptedException {
log.info("开始任务一");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务一、耗时:"+(end-start)+"毫秒");
}
@Async("taskExecutor")
public void doTaskTwo() throws InterruptedException {
log.info("开始任务二");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务二、耗时:"+(end-start)+"毫秒");
}
@Async("taskExecutor")
public void doTaskThree() throws InterruptedException {
log.info("开始任务三");
long start = System.currentTimeMillis();
Thread.sleep(random.nextInt(10000));
long end = System.currentTimeMillis();
log.info("完成任务三、耗时:"+(end-start)+"毫秒");
}
}
-
3 执行结果
task.jpg
异步回调
有时我们需要对异步调用的结果进行相关的处理,此时需要进行相应的回掉。具体操作如下:
/***
*
*/
@Component
@Slf4j
public class AsyncTask {
@Async("taskExecutor")
public Future<String> doTask() throws InterruptedException {
log.info("Task1 started");
long start = System.currentTimeMillis();
Thread.sleep(5000);
long end = System.currentTimeMillis();
log.info("Task1 finished,time elapsed:{} ms",end-start);
return new AsyncResult<>("Task1 accomplished");
}
@Async("taskExecutor")
public Future<String> doTask2() throws InterruptedException {
log.info("Task2 started");
long start = System.currentTimeMillis();
Thread.sleep(3000);
long end = System.currentTimeMillis();
log.info("Task2 finished,time elapsed:{} ms",end-start);
return new AsyncResult<>("Task2 accomplished");
}
}
异步回调结果在单元测试的主类中
单元测试
package com.example.springbootasync;
import com.example.springbootasync.sync.SyncTask;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
@RunWith(SpringRunner.class)
@SpringBootTest
@Slf4j
public class SpringbootasyncApplicationTests {
@Autowired
private Task task;
@Autowired
private AsyncTask asyncTask;
@Autowired
private SyncTask syncTask;
@Test
public void syncTaskTest() throws InterruptedException {
syncTask.doTaskOne();
syncTask.doTaskTwo();
syncTask.doTaskThree();
}
@Test
public void contextLoads() throws InterruptedException {
task.doTaskOne();
task.doTaskTwo();
task.doTaskThree();
Thread.currentThread().join();
}
@Test
public void AsyncTaskTest() throws InterruptedException, ExecutionException {
Future<String> task1 = asyncTask.doTask();
Future<String> task2 = asyncTask.doTask2();
while(true){
if(task1.isDone() && task2.isDone()){
log.info("TASK1 result: {}",task1.get());
log.info("TASK2 result: {}",task2.get());
break;
}
Thread.sleep(1000);
}
log.info("All tasks finished.");
}
}
总结
通过以上操作,我们对同步与异步进行了一定的了解。通过代码对异步回调有初步的认识。但是在一些具体的业务场景中如何处理,需要进行相应的场景修改。
码云地址:https://gitee.com/huangjian163/springbootSync.git
网友评论