代码日记:
实现一个需求,多线程嵌套多线程最后调用feign接口,请求某个微服务。容易出现请求头丢失的情况,
报错 The request object has been recycled and is no longer associated with this facade
现在用本地线程变量来接受存储。
Java 使用线程池,父子孙之间传递参数。思路使用 TransmittableThreadLocal
代码1:
public class holder {
private static final TransmittableThreadLocal<ServletRequestAttributes> requestHolder = new TransmittableThreadLocal<>();
public static void set(ServletRequestAttributes request) {
requestHolder.set(request);
}
public static ServletRequestAttributes get() {
return requestHolder.get();
}
public static void remove() {
requestHolder.remove();
}
}
代码2:在主程序
ConcurrentHashMap<String, Object> lists = new ConcurrentHashMap<>();
int threadCount = 4;
CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
try {
for (int i = 1; i < threadCount; i++) {
int finalI = i;
fixedThreadPool.submit(() -> {
holder.set(servletRequestAttributes);
try {
if (finalI == 1) {
lists.put("xx", XXX(id));
} else if (finalI == 2) {
lists.put("xx", XXX(id);
}
} catch (
Exception e) {
e.printStackTrace();
} finally {
holder.remove();
try {
cyclicBarrier.await();
} catch (
Exception e) {
e.printStackTrace();
}
}
});
}
} catch (
Exception e) {
e.printStackTrace();
} finally {
cyclicBarrier.await();
}
代码3 在XXX方法中
ServletRequestAttributes servletRequestAttributes = holder.get();
int threadCount = 4;
CyclicBarrier cyclicBarrier = new CyclicBarrier(threadCount);
try {
for (int i = 1; i < threadCount; i++) {
int finalI = i;
fixedThreadPool.submit(() -> {
holder.set(servletRequestAttributes);
try {
if (finalI == 1){
List<Map<String, Object>> apple = YYY(id);
ref.lists.addAll(apple);
}else if (finalI == 2){
List<Map<String, Object>> bannana = YYY(id);
ref.lists.addAll(bannana);
} }catch (Exception e) {
e.printStackTrace();
} finally {
try {
holder.remove();
cyclicBarrier.await();
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
}finally {
cyclicBarrier.await();
}
代码4 在YYY方法中 最终
ServletRequestAttributes servletRequestAttributes = ViewHolder.get();
for (int i = 0; i < poolNumber; i++) {
int finalI = i;
fixedThreadPool.execute(()->{
try{
//feign接口调用另一个服务,需要用到http请求头
feign.eat();
}
}