多线程 RequestContextHolder.getRequestAttributes 空指针错误

代码如下:

public interface ThreadTaskService {

	@Async
	Future task1();
	@Async
	Future task2();
	@Async
	Future task3();

}

package com.dh.springcloud.test.server;

import java.util.concurrent.Future;

import javax.servlet.http.HttpServletRequest;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Service
public class ThreadTaskServiceImpl implements ThreadTaskService {

	private static final Logger LOGGER = LoggerFactory.getLogger(ThreadTaskServiceImpl.class);

	@Override
	public Future task1() {
		LOGGER.info("===进入task1===");
		try {
			Thread.sleep(2000);
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			LOGGER.info("request url:" + request.getRequestURL());
			String threadName = Thread.currentThread().getName();
			LOGGER.info("===当前线程名===" + threadName);
			AsyncResult asyncResult = new AsyncResult<>(threadName + " is finished");
			return asyncResult;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new AsyncResult<>("fail");
	}

	@Override
	public Future task2() {
		LOGGER.info("===进入task2===");
		try {
			Thread.sleep(2000);
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			LOGGER.info("request url:" + request.getRequestURL());
			String threadName = Thread.currentThread().getName();
			LOGGER.info("===当前线程名===" + threadName);
			AsyncResult asyncResult = new AsyncResult<>(threadName + " is finished");
			return asyncResult;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new AsyncResult<>("fail");
	}

	@Override
	public Future task3() {
		LOGGER.info("===进入task3===");
		try {
			Thread.sleep(2000);
			HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
					.getRequest();
			LOGGER.info("request url:" + request.getRequestURL());
			String threadName = Thread.currentThread().getName();
			LOGGER.info("===当前线程名===" + threadName);
			AsyncResult asyncResult = new AsyncResult<>(threadName + " is finished");
			return asyncResult;
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return new AsyncResult<>("fail");
	}

}

Controller层

	@GetMapping("/testTask")
	public Object testTask() throws InterruptedException, ExecutionException {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		LOGGER.info("request url:" + request.getRequestURL());
		long st = System.currentTimeMillis();
		Future task1 = service.task1();
		Future task2 = service.task2();
		Future task3 = service.task3();
		while (true) {
			if (task1.isDone() && task2.isDone() && task3.isDone()) {
				LOGGER.info("所有子线程已执行完成");
				break;
			}
		}
		long et = System.currentTimeMillis();
		LOGGER.info("---耗时---: " + (et - st));
		List arrayList = new ArrayList();
		arrayList.add(task1.get());
		arrayList.add(task2.get());
		arrayList.add(task3.get());
		Map map = new HashMap<>();
		map.put("code", 200);
		map.put("msg", "success");
		map.put("data", arrayList);
		return map;
	}

多线程 RequestContextHolder.getRequestAttributes 空指针错误_第1张图片

解决方法:
在执行多线程前,将RequestAttributes对象设置为子线程共享
RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);

@GetMapping("/testTask")
	public Object testTask() throws InterruptedException, ExecutionException {
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		LOGGER.info("request url:" + request.getRequestURL());
		RequestContextHolder.setRequestAttributes(RequestContextHolder.getRequestAttributes(), true);
		long st = System.currentTimeMillis();

		Future task1 = service.task1();
		Future task2 = service.task2();
		Future task3 = service.task3();
		while (true) {
			if (task1.isDone() && task2.isDone() && task3.isDone()) {
				LOGGER.info("所有子线程已执行完成");
				break;
			}
		}
		long et = System.currentTimeMillis();
		LOGGER.info("---耗时---: " + (et - st));
		List arrayList = new ArrayList();
		arrayList.add(task1.get());
		arrayList.add(task2.get());
		arrayList.add(task3.get());
		Map map = new HashMap<>();
		map.put("code", 200);
		map.put("msg", "success");
		map.put("data", arrayList);
		return map;
	}

参考:
https://www.cnblogs.com/Terry-Wu/p/9439126.html

https://blog.csdn.net/weixin_44251024/article/details/86544900

你可能感兴趣的:(springcloud学习,springboot学习)