ThreadPool和ThreadLocal的区别
时间: 2023-11-01 11:58:07 浏览: 111
ThreadPool和ThreadLocal是Java多线程编程中的两个重要概念,它们有以下区别:
ThreadPool(线程池)是一种管理和复用线程的机制,它可以在需要时创建线程,并在任务完成后重用这些线程。通过线程池可以有效地控制线程的数量,避免频繁地创建和销毁线程带来的资源开销。ThreadPool适用于需要大量异步任务的场景,可以提高程序的性能和响应速度。
ThreadLocal(线程局部变量)是一种线程级别的数据存储机制,它可以为每个线程提供独立的变量副本,每个线程都可以对自己的副本进行读写操作,而不会影响其他线程的副本。ThreadLocal适用于需要在线程间隔离数据的场景,比如在Web应用中,可以将请求相关的数据存储到ThreadLocal中,保证每个请求线程都能够独立地访问自己的数据。
综上所述,ThreadPool用于管理和复用线程,而ThreadLocal用于在线程间隔离数据。虽然它们都与线程相关,但功能和应用场景不同。
相关问题
使用 ThreadLocal 的线程池
使用 ThreadLocal 的线程池可以提高线程池的性能和可靠性,因为它可以避免线程间的竞争和线程上下文的切换。
具体实现方法如下:
1. 定义一个继承自ThreadPoolExecutor的线程池类,重写newThread方法,在其中创建一个ThreadLocal对象。
2. 在执行任务之前,通过ThreadLocal.get()方法获取当前线程的任务队列,将任务加入队列。
3. 在执行任务时,通过ThreadLocal.get()方法获取当前线程的任务队列,从队列中取出任务进行执行。
4. 在任务执行完成后,通过ThreadLocal.get()方法获取当前线程的任务队列,将队列清空。
这样做的好处是,每个线程都有自己独立的任务队列,避免了线程间的竞争,同时也减少了线程上下文的切换,提高了线程池的性能和可靠性。
以下是一个简单的示例代码:
```java
public class ThreadLocalThreadPool extends ThreadPoolExecutor {
private ThreadLocal<Queue<Runnable>> taskQueue = new ThreadLocal<>();
public ThreadLocalThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
}
@Override
protected void beforeExecute(Thread t, Runnable r) {
Queue<Runnable> queue = taskQueue.get();
if (queue == null) {
queue = new LinkedList<>();
taskQueue.set(queue);
}
queue.offer(r);
}
@Override
protected void afterExecute(Runnable r, Throwable t) {
Queue<Runnable> queue = taskQueue.get();
queue.clear();
}
@Override
protected Thread newThread(Runnable r) {
return new Thread(r);
}
}
```
使用时,可以直接创建一个ThreadLocalThreadPool对象,并将任务提交到线程池中。
```java
ThreadLocalThreadPool threadPool = new ThreadLocalThreadPool(5, 10, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<>());
for (int i = 0; i < 100; i++) {
threadPool.submit(new Task());
}
```
@Override public HomePagePopupResp getPopupData(HomePagePopupReq req) throws BusinessException { HomePagePopupResp homePagePopupResp = new HomePagePopupResp(); RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); try { // 创建线程池 ThreadPoolExecutor threadPool = new ThreadPoolExecutor(3, 20, 0, TimeUnit.SECONDS, new LinkedBlockingDeque<>(1024)); // 添加任务 threadPool.submit(new Runnable() { @Override public void run() { // /api/project-m-sit01/srv/intelFive/queryNoFinishMeetTenDay 通过用户ID查询距离回收日期10天内的已电约完成且未面见完成的客户(每天进入app首页弹出一次) List<NoFinishThreeDayResp> queryNoFinishMeetTenDayList = intelFiveService.queryNoFinishMeetTenDay(req.getMeetNoFinishTenDayReq()); if (CollectionUtil.isNotEmpty(queryNoFinishMeetTenDayList)){ homePagePopupResp.setQueryNoFinishMeetTenDayList(queryNoFinishMeetTenDayList); } log.info(String.format("/outer/homePage/popup >>>>任务QueryNoFinishMeetTenDayList执行完成")); } }); threadPool.submit(new Runnable() { @Override public void run() { // /api/project-m-sit01/srv/intelFive/queryNoFinishThreeDay 通过用户ID查询距离回收日期3天内的未完成电约的客户(每天进入app首页弹出一次) List<NoFinishThreeDayResp> noFinishThreeDayRespList = intelFiveService.queryNoFinishThreeDay(req.getUserCustRecordReq()); if (CollectionUtil.isNotEmpty(noFinishThreeDayRespList)){ homePagePopupResp.setNoFinishThreeDayRespList(noFinishThreeDayRespList); } log.info(String.format("/outer/homePage/popup >>>>任务NoFinishThreeDayRespList执行完成")); } }); threadPool.submit(new Runnable() { @Override public void run() { ///api/assess-sit01/srv/assess/poster/popupPoster 弹出海报,登录APP时调用 Map listR = assessRemoteService.doPopupPoster(req.getPosterReq()); if (ObjectUtil.isNotNull(listR)){ homePagePopupResp.setPosterRespList(listR); } log.info(String.format("/outer/homePage/popup >>>>任务PosterRespList执行完成")); } }); threadPool.shutdown(); }catch (Exception e){ throw new BusinessException("/outer/homePage/popup 调用失败"); } // ///api/project-m-sit01/srv/smart5/queryNewsCount?isChange=1 查询未接来电弹框状态 // AppelManqueClickResp appelManqueClickResp = appelManqueService.queryNewsCount(req.getIsChange()); // homePagePopupResp.setAppelManqueClickResp(appelManqueClickResp); return homePagePopupResp; } 该段代码 子线程如何获取请求头参数
子线程可以通过ThreadLocal来获取请求头参数。在主线程中,可以将请求头参数存储在ThreadLocal中,子线程可以通过ThreadLocal获取存储的请求头参数。具体实现可以参考以下代码:
```
// 在主线程中存储请求头参数到ThreadLocal中
ThreadLocal<Map<String, String>> threadLocal = new ThreadLocal<>();
threadLocal.set(requestAttributes.getAttribute("headerParams", RequestAttributes.SCOPE_REQUEST));
// 在子线程中获取请求头参数
threadPool.submit(new Runnable() {
@Override
public void run() {
// 从ThreadLocal中获取请求头参数
Map<String, String> headerParams = threadLocal.get();
// 子线程中的代码
}
});
```
阅读全文
相关推荐











