为什么不适用new Thread创建线程?
①线程多了不一定快 ------ 线程是CPU(或操作系统)的一个资源,如果手动去创建一个线程,例如一个高并发项目十万人访问,每个用户创建一个线程,对于操作系统来说就会创建很多线程,这些线程就会抢夺CPU资源,造成线程调度频繁
②容易出现OOM ------ 来了多少请求就创建多少线程
线程池原理:当主线程调用execute方法或submit方法提交任务到线程池里面的时候,有空闲核心线程就交给核心线程去处理,核心线程用完,先进入阻塞队列(先进先出的队列),此时任务没有被执行,核心线程如果空闲就会读取阻塞队列的任务去执行。如果阻塞队列满了,主线程继续提交任务,就会判断当前线程池的容量是否达到了最大线程,如果没有达到最大线程,就会创建新的线程去执行阻塞队列的任务或用户提交的任务。如果达到最大线程就会执行拒绝策略。
核心线程的特点:①没有任务的时候,核心线程可以全部创建好
②没有任务的时候,核心线程不可以回收
拒绝策略:
①饱和策略(AbortPolicy) 这个线程池到达饱和状态以后,直接把主线程提交的任务抛个异常出来,告诉主线程当前线程池已经饱和了
②调用者运行(CallerRunsPolicy) 有一些交易订单请求不能直接抛掉,比如请求中带有金额,线程池会把不能执行的任务再放回到主线程,让主线程执行,主线程就会变成一个串行过程。
Java有多少中线程池?
Java里面只有一种线程池ThreadPoolExecutor
线程池原理图
Guava对Java线程的改进
① Guava为Java并行编程Future提供了很多有用扩展,其主要接口为ListenableFuture,并借助于Futures静态扩展。
②继承自Future的ListenableFuture,允许我们添加回调函数,在线程运算完成时执行回调函数。
③如果Future带有回调,这样是不是可以避免我们直接操作get()获取返回值。
1.JDK线程池使用
@RestController
public class JdkThreadController {
@Resource
private OuterService outerService;
@RequestMapping("/test/jdk")
public Map<String, Object> execute() throws ExecutionException, InterruptedException {
// 固定大小的线程池 核心线程数和最大线程数=10
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 记录开始时间
Long start = System.currentTimeMillis();
// 异步调用用户服务
Future<Long> userServiceFuture = executorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.userService();
}
});
// 异步调用订单服务
Future<Long> orderServiceFuture = executorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.orderService();
}
});
// 异步调用商品服务
Future<Long> itemServiceFuture = executorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.itemService();
}
});
// 阻塞 等待执行结果
long userServiceResult = userServiceFuture.get();
long orderServiceResult = orderServiceFuture.get();
long itemServiceResult = itemServiceFuture.get();
//结束调用的时间
long end = System.currentTimeMillis();
//计算结果
long result = userServiceResult + orderServiceResult + itemServiceResult;
String time = "总调用时间是:" + (end - start) + "毫秒";
//为什么要初始化4个容量的Map
Map<String, Object> resultMap = new HashMap<>(4);
resultMap.put("time", time);
resultMap.put("result", result);
//结果
return resultMap;
}
}
@Service
public class OuterService {
/**
* 用户服务
*/
public long userService() {
System.out.println("用户服务开始执行");
try {
//模拟耗时1000ms的用户服务
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户服务执行结束");
//假设用户服务返回值=1
return 1;
}
/**
* 订单服务
*/
public long orderService() {
System.out.println("订单服务开始执行");
try {
//模拟耗时2000ms的订单服务
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("订单服务执行结束");
//假设订单服务返回值=3
return 3;
}
/**
* 商品服务
*/
public long itemService() {
System.out.println("商品服务开始执行");
try {
//模拟耗时3000ms的商品服务
Thread.sleep(3000);
//模拟调用超时或者服务异常
// throw new RuntimeException("Oh My God, OrderService Exception!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("商品服务执行结束");
//假设商品服务返回值=5
return 5;
}
/**
* 地址服务
*/
public long addressService() {
System.out.println("地址服务开始执行");
try {
//模拟耗时5000ms的地址服务
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("地址服务执行结束");
//假设地址服务返回值=7
return 7;
}
}
2.guava线程池使用
/**
- 2.1公用的线程池
*/
@Component
public class ListeningExecutors {
@Bean
public ListeningExecutorService createListeningExecutorService(){
//创建线程池
return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
}
}
public class FutureCallBackTask implements FutureCallback<Object> {
/**
* 成功的回调
* @param result
*/
@Override
public void onSuccess(Object result) {
//执行回调函数
System.out.println("进入正确的回调函数");
//得到任务执行的结果
System.out.printf("任务执行的结果是:%s%n", result);
}
/**
* 失败的回调
* @param thrown
*/
@Override
public void onFailure(Throwable thrown) {
System.out.println("进入错误的回调函数");
System.out.printf("系统出错了,错误原因是:%s%n", thrown.getMessage());
}
}
@RestController
public class GuavaThreadController {
@Autowired
private ListeningExecutorService listeningExecutorService;
@RequestMapping("/test/guava")
public void execute(){
//一个耗时的任务
ListenableFuture<Boolean> listenableFuture = listeningExecutorService.submit(() -> {
Thread.sleep(5000);
return true;
});
//注册回调事件
Futures.addCallback(listenableFuture,new FutureCallBackTask(),listeningExecutorService);
}
}
另一种优化方案,不改动公司内部的线程池
@Component
public class ListeningExecutors {
@Bean
public ListeningExecutorService createListeningExecutorService() {
// 创建线程池
return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
}
}
public class FutureCallBackTask implements FutureCallback<Object> {
/**
* 成功的回调
* @param result
*/
@Override
public void onSuccess(Object result) {
//执行回调函数
System.out.println("进入正确的回调函数");
//得到任务执行的结果
System.out.printf("任务执行的结果是:%s%n", result);
}
/**
* 失败的回调
* @param thrown
*/
@Override
public void onFailure(Throwable thrown) {
System.out.println("进入错误的回调函数");
System.out.printf("系统出错了,错误原因是:%s%n", thrown.getMessage());
}
}
@RestController
public class JdkFutureAdaptersController {
@Autowired
private ListeningExecutorService listeningExecutorService;
@RequestMapping("/test/adapter")
public void execute(){
// 记录开始时间
Long start = System.currentTimeMillis();
// 一个耗时的任务
Future<Boolean> future = listeningExecutorService.submit(new Callable<Boolean>() {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
@Override
public Boolean call() throws Exception {
//模拟耗时5s
Thread.sleep(5000);
return true;
}
});
ListenableFuture<Boolean> listenableFuture = JdkFutureAdapters.listenInPoolThread(future);
Futures.addCallback(listenableFuture,new FutureCallBackTask(),listeningExecutorService);
}
}
最后,guava的高级特性使用
@Component
public class ListeningExecutors {
@Bean
public ListeningExecutorService createListeningExecutorService() {
// 创建线程池
return MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(10));
}
}
@Service
public class OuterService {
/**
* 用户服务
*/
public long userService() {
System.out.println("用户服务开始执行");
try {
//模拟耗时1000ms的用户服务
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("用户服务执行结束");
//假设用户服务返回值=1
return 1;
}
/**
* 订单服务
*/
public long orderService() {
System.out.println("订单服务开始执行");
try {
//模拟耗时2000ms的订单服务
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("订单服务执行结束");
//假设订单服务返回值=3
return 3;
}
/**
* 商品服务
*/
public long itemService() {
System.out.println("商品服务开始执行");
try {
//模拟耗时3000ms的商品服务
Thread.sleep(3000);
//模拟调用超时或者服务异常
// throw new RuntimeException("Oh My God, OrderService Exception!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("商品服务执行结束");
//假设商品服务返回值=5
return 5;
}
/**
* 地址服务
*/
public long addressService() {
System.out.println("地址服务开始执行");
try {
//模拟耗时5000ms的地址服务
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("地址服务执行结束");
//假设地址服务返回值=7
return 7;
}
}
/**
* @Description: 高级特性介绍
* <p>
* transform:对于ListenableFuture的返回值进行转换。
* <p>
* allAsList:对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。
* 注:当其中一个Future失败或者取消的时候,将会进入失败或者取消。
* <p>
* successfulAsList:和allAsList相似,唯一差别是对于失败或取消的Future返回值用null代替。不会进入失败或者取消流程。
* <p>
* immediateFuture/immediateCancelledFuture: 立即返回一个待返回值的ListenableFuture。
* <p>
* makeChecked: 将ListenableFuture 转换成CheckedFuture。CheckedFuture 是一个ListenableFuture 。
* 其中包含了多个版本的get 方法,方法声明抛出检查异常.这样使得创建一个在执行逻辑中可以抛出异常的Future更加容易
* <p>
* JdkFutureAdapters.listenInPoolThread(jdkthread): guava同时提供了将JDK Future转换为ListenableFuture的接口函数。
*/
@RestController
public class SeniorListenableFutureController {
@Autowired
private ListeningExecutorService listeningExecutorService;
@Autowired
private OuterService outerService;
@RequestMapping("/test/senior")
public Map<String, Object> execute() throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
// 异步调用用户服务
ListenableFuture<Long> userServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.userService();
}
});
// 异步调用订单服务
ListenableFuture<Long> orderServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.orderService();
}
});
// 异步调用商品服务
ListenableFuture<Long> itemServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.itemService();
}
});
//注册商品服务回调
addCallBack(itemServiceFuture);
// .......
// 对多个ListenableFuture的合并,返回一个当所有Future成功时返回多个Future返回值组成的List对象。
// 注:当其中一个Future失败或者取消的时候,会怎样?
//拿到三个任务的成功执行结果
final ListenableFuture<List<Long>> threeServicesFutures = Futures.successfulAsList(userServiceFuture, orderServiceFuture, itemServiceFuture);
//对于多个ListenableFuture的进行转换,返回一个新的ListenableFuture
final ListenableFuture<Long> transform = Futures.transformAsync(threeServicesFutures, new AsyncFunction<List<Long>, Long>() {
/**
* 用给定的输入封装一个特定的ListenableFuture作为输出
*
* @param input 输入的ListenableFuture对象
*/
@Override
public ListenableFuture<Long> apply(@Nullable List<Long> input) {
if (input == null || input.isEmpty()) {
return null;
}
// 这里可以对input进行复杂的处理,返回最终的一个结果
// 比如:对用户服务,订单服务,商品服务的远程调用结果进行封装
long result = 0;
for (Long serviceResult : input) {
if (serviceResult != null) {
result += serviceResult;
}
}
// 立即返回一个带返回值的ListenableFuture
return Futures.immediateFuture(result);
}
}, listeningExecutorService);
// 异步调用地址服务
ListenableFuture<Long> addressServiceFuture = listeningExecutorService.submit(new Callable<Long>() {
@Override
public Long call() throws Exception {
return outerService.addressService();
}
});
final ListenableFuture<List<Long>> finalFutures = Futures.successfulAsList(transform, addressServiceFuture);
ListenableFuture<Long> finalResult = Futures.transformAsync(finalFutures, new AsyncFunction<List<Long>, Long>() {
@Override
public ListenableFuture<Long> apply(@Nullable List<Long> input) throws Exception {
if (CollectionUtils.isEmpty(input)) {
return null;
}
// 这里可以对input进行复杂的处理,返回最终的一个结果
long result = 0;
// 比如:对上面的用户服务,订单服务,商品服务的总结果和地址服务再封装
for (Long serviceResult : input) {
if (serviceResult != null) {
result += serviceResult;
}
}
// 立即返回一个带返回值的ListenableFuture
return Futures.immediateFuture(result);
}
}, listeningExecutorService);
// 注册回调事件
addCallBack(finalResult);
long end = System.currentTimeMillis();
String time = "总调用时间是:" + (end - start) + "毫秒";
//为什么要初始化4个容量的Map
Map<String, Object> resultMap = new HashMap<>(3);
resultMap.put("time", time);
//结果
return resultMap;
}
/**
* 添加回调
* @param listenableFuture
*/
private void addCallBack(ListenableFuture<Long> listenableFuture) {
Futures.addCallback(listenableFuture, new FutureCallback<Long>() {
@Override
public void onSuccess(@Nullable Long result) {
System.out.printf("服务调用成功,执行结果是%s%n",result);
}
@Override
public void onFailure(Throwable t) {
System.out.printf("服务调用异常%s%n", t);
}
}, listeningExecutorService);
}
}