线程池使用场景CountDownLatch
CountDownLatch
CountDownlatch (闭锁/倒计时锁)用来进行线程同步协作,等待所有线程完成倒计时(一个或者多个线程,等待其他多个线程完成某件事情之后才能执行)
其中构造参数用来初始化等待计数值
await0用来等待计数归零
countDown0用来让计数减一
**
案例一(es数据批量导入)
**
在我们项目上线之前,我们需要把数据库中的数据一次性的同步到es索引库中,但是当时的数据好像是1000万左右,一次性读取数据肯定不行(oom异常),当时我就想到可以使用线程池的方式导入,利用CountDownLatch来控制,就能避免一次性加载过多,防止内存溢出
案例二(数据汇总)
在实际开发的过程中,难免需要调用多个接口来汇总数据,如果所有接口(或部分接口)的没有依赖关系,就可以
使用线程池+future来提升性能
Future<Map<String, Object>> f1 = executorService.submit(() -> {
Map<String, Object> r =
restTemplate.getForObject("http://localhost:9991/order/get/{id}", Map.class, 1);
return r;
});
Future<Map<String, Object>> f2 = executorService.submit(() -> {
Map<String, Object> r =
restTemplate.getForObject("http://localhost:9991/product/get/{id}", Map.class, 1);
return r;
});
Future<Map<String, Object>> f3 = executorService.submit(() -> {
Map<String, Object> r =
restTemplate.getForObject("http://localhost:9991/logistics/get/{id}", Map.class, 1);
return r;
});
Map<String, Object> resultMap = new HashMap<>();
resultMap.put("order", f1.get());
resultMap.put("product", f2.get());
resultMap.put("logistics", f3.get());
场景3:异步线程 (线程池)
为了避免下一级方法影响上一级方法(性能考虑),可使用异步线程调用下一个方法(不需要下一级方法返回值),可以提升方法响应时间
如何控制某个方法允许并发访问线程的数量
// 1. 创建 semaphore 对象
Semaphore semaphore = new Semaphore(3);
// 3. 获取许可,计数-1
semaphore.acquire();
// 4. 释放许可 计数+1
semaphore.release();
在多线程中提供了一个工具类Semaphore,信号量。在并发的情况下,可以控制方法的访问量
1.创建Semaphore对象,可以给一个容量
2. acquire0可以请求一个信号量,这时候的信号量个数**-1**
release()释放一个信号量,此时信号量个数+1
请你谈谈Threadlocal的理解
1.ThreadLocal可以实现[资源对象]的线程隔离,让每个线程各用各的[资源对象)避免争用引发的线程安全问题
2.ThreadLocal同时实现了线程内的资源共享
3.每个线程内有一个ThreadLocalMap 类型的成员变量,用来存储资源对象
a)调用set 方法,就是以ThreadLocal自己作为 key,资源对象作为 value,放入当前线程的ThreadLocalMap 集合中
b)调用get方法,就是以ThreadLocal 自己作为 key,到当前线程中查找关联的资源值c)调用remove 方法,就是以ThreadLocal自己作为 key,移除当前线程关联的资源值
4.ThreadLocal内存泄漏问题
ThreadLocalMap中的 key 是弱用,值为强引用; key 会被GC释放内存,关联value的内存并不会释放。建议主动 remove释放 key,value