何谓异步?
每次调用都创建一个新的线程去执行, 不会等待上一次调用执行完,再执行下一个请求
SpringBoot项目怎么做
- 在启动类上添加:@EnableAsync 注解
- 项目中添加下面两个类
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import com.imooc.miaoshaproject.util.Threads;
import org.apache.commons.lang3.concurrent.BasicThreadFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
/**
* 线程池配置
**/
@Configuration
public class ThreadPoolConfig
{
// 核心线程池大小
private int corePoolSize = 50;
// 最大可创建的线程数
private int maxPoolSize = 200;
// 队列最大长度
private int queueCapacity = 1000;
// 线程池维护线程所允许的空闲时间
private int keepAliveSeconds = 300;
@Bean(name = "threadPoolTaskExecutor")
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setMaxPoolSize(maxPoolSize);
executor.setCorePoolSize(corePoolSize);
executor.setQueueCapacity(queueCapacity);
executor.setKeepAliveSeconds(keepAliveSeconds);
// 线程池对拒绝任务(无线程可用)的处理策略
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
return executor;
}
/**
* 执行周期性或定时任务
*/
@Bean(name = "scheduledExecutorService")
protected ScheduledExecutorService scheduledExecutorService()
{
return new ScheduledThreadPoolExecutor(corePoolSize,
new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build())
{
@Override
protected void afterExecute(Runnable r, Throwable t)
{
super.afterExecute(r, t);
Threads.printException(r, t);
}
};
}
}
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.concurrent.*;
/**
* 线程相关工具类.
*
*/
public class Threads
{
private static final Logger logger = LoggerFactory.getLogger(Threads.class);
/**
* sleep等待,单位为毫秒
*/
public static void sleep(long milliseconds)
{
try
{
Thread.sleep(milliseconds);
}
catch (InterruptedException e)
{
return;
}
}
/**
* 停止线程池
* 先使用shutdown, 停止接收新任务并尝试完成所有已存在任务.
* 如果超时, 则调用shutdownNow, 取消在workQueue中Pending的任务,并中断所有阻塞函数.
* 如果仍人超時,則強制退出.
* 另对在shutdown时线程本身被调用中断做了处理.
*/
public static void shutdownAndAwaitTermination(ExecutorService pool)
{
if (pool != null && !pool.isShutdown())
{
pool.shutdown();
try
{
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
pool.shutdownNow();
if (!pool.awaitTermination(120, TimeUnit.SECONDS))
{
logger.info("Pool did not terminate");
}
}
}
catch (InterruptedException ie)
{
pool.shutdownNow();
Thread.currentThread().interrupt();
}
}
}
/**
* 打印线程异常信息
*/
public static void printException(Runnable r, Throwable t)
{
if (t == null && r instanceof Future<?>)
{
try
{
Future<?> future = (Future<?>) r;
if (future.isDone())
{
future.get();
}
}
catch (CancellationException ce)
{
t = ce;
}
catch (ExecutionException ee)
{
t = ee.getCause();
}
catch (InterruptedException ie)
{
Thread.currentThread().interrupt();
}
}
if (t != null)
{
logger.error(t.getMessage(), t);
}
}
}
- 在需要异步调用的接口上添加@Async(“threadPoolTaskExecutor”)注解即可
@Async("threadPoolTaskExecutor")
@RequestMapping(value = "/test",method = {RequestMethod.GET,RequestMethod.POST})
@ResponseBody
public void test() {
System.out.println("===test===");
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}