当前位置: 首页 > news >正文

开启多线程下变量共享与私有问题

开启多线程下变量共享与私有问题

🌵ThreadLocal和Atomic是Java中用于多线程编程的两个重要工具

ThreadLocal是一个线程局部变量,它为每个线程提供了独立的变量副本,确保每个线程都可以访问自己的变量副本而不会影响其他线程的变量。在多线程环境下,使用ThreadLocal可以避免线程安全问题。

Atomic是一组原子操作类,提供了一些常见的原子操作,如原子更新整型、原子更新引用等。在多线程环境下,使用Atomic可以保证操作的原子性,避免出现数据竞争和线程安全问题

🎯下面是一个简单的示例ThreadLocal和Atomic在多线程环境下的用法:

import java.util.concurrent.atomic.AtomicInteger;public class ThreadLocalAndAtomicExample {private static ThreadLocal<Integer> threadLocal = ThreadLocal.withInitial(() -> 0);private static AtomicInteger atomicInteger = new AtomicInteger(0);public static void main(String[] args) {for (int i = 0; i < 5; i++) {new Thread(() -> {int localValue = threadLocal.get();localValue++;threadLocal.set(localValue);int atomicValue = atomicInteger.incrementAndGet();System.out.println("ThreadLocal value: " + threadLocal.get() + " Atomic value: " + atomicValue);}).start();}}
}

在上面的示例中,我们创建了一个ThreadLocal变量和一个AtomicInteger变量,然后启动了5个线程,每个线程对这两个变量进行操作。通过输出结果可以看到,ThreadLocal变量在每个线程中独立维护了自己的值,而AtomicInteger变量则保证了操作的原子性。

总结来说,在多线程编程中,ThreadLocal可以用于保证每个线程拥有独立的变量副本,避免线程安全问题;而Atomic可以用于保证操作的原子性,避免数据竞争和线程安全问题。在实际开发中,我们可以根据具体需求选择合适的工具来保证多线程程序的正确性和性能。

🎯下面是一个类似的示例,多线程使用EasyExcel处理导出数据,使用ExecutorService、CountDownLatch、ThreadLocal和Atomic在多线程环境下的用法:

   public void exportAllApply(HttpServletResponse response, ApplyScope applyScope){SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");String fileName = "APPLY" + +"-"+Calendar.getInstance().getTimeInMillis()+".xlsx";List<ApplyExportVo> allApply = new ArrayList<>();try {ExcelWriter excelWriter = EasyExcel.write(fileName, ApplyExportVo.class).build();WriteSheet writeSheet = EasyExcel.writerSheet("sheet1").build();int threadCount = 5;//默认开启五个线程ExecutorService executorService = Executors.newFixedThreadPool(threadCount);CountDownLatch latch = new CountDownLatch(threadCount);ThreadLocal<ApplyScope> threadLocalApply = ThreadLocal.withInitial(ApplyScope::new);AtomicLong updatePage = new AtomicLong(1);for (int i = 0; i < threadCount; i++) {int finalI = i+1;executorService.execute(() -> {ApplyScope localApply = threadLocalApply.get();BeanUtils.copyProperties(applyScope,localApply);while (true) {long currentPage = updatePage.getAndIncrement();//更新分页信息,需同步updatePage(localApply, currentPage);ApplyGeneralVo applyGeneralVo = this.queryApplyView(localApply);List<ApplyVo> applyList = applyGeneralVo.getApplyList();log.info("线程threadCount:"+finalI+"当前页码"+currentPage+",数量"+applyList.size());if(CollectionUtils.isEmpty(applyList)){break;}List<ApplyExportVo> exportVos = BeanUtil.toBeanList(applyList, ApplyExportVo.class);allApply.addAll(exportVos);}latch.countDown();});}executorService.shutdown();latch.await();Long startWrite = Calendar.getInstance().getTimeInMillis();Optional.ofNullable(allApply).ifPresent(data -> {excelWriter.write(data, writeSheet);});excelWriter.finish();log.info("----- writeExcelTime:" + (Calendar.getInstance().getTimeInMillis() - startWrite));} catch (Exception e) {e.printStackTrace();}
}private synchronized long updatePage(ApplyScope scope, long current){PageScope page = scope.getPages();if(page == null){page = new PageScope();page.setSize(1000L);page.setCurrent(current);scope.setPages(page);} else {page.setCurrent(current);}return page.getCurrent();
}

🚩在上面的示例中,我们创建了一个固定大小的线程池ExecutorService,并使用CountDownLatch来等待所有线程执行完毕。每个线程在执行时会对ThreadLocal变量和AtomicInteger变量进行操作,并在操作完成后调用CountDownLatch的countDown()方法来通知主线程。

通过输出结果可以看到,每个线程中的ThreadLocal变量和AtomicInteger变量都能够正确地保持独立和原子性,同时CountDownLatch确保了所有线程执行完毕后主线程才会继续执行。

http://www.lryc.cn/news/346266.html

相关文章:

  • Qt模型视图代理之QTableView应用的简单介绍
  • 第七届精武杯部分wp
  • 3.2Java全栈开发前端+后端(全栈工程师进阶之路)-前端框架VUE3框架-企业级应用- Vuex
  • 整合 Java, Python 和 Scrapy 爬虫以传递和使用参数
  • Android 蓝牙实战——蓝牙音乐播放进度(二十)
  • SQL注入实例(sqli-labs/less-1)
  • Python中tkinter编程入门3
  • XMind 2023 v23.05.2660软件安装教程(附软件下载地址)
  • docker compose kafka集群部署
  • 最新版在线客服系统源码
  • 【比邻智选】MR880A模组
  • 超大文件去除重复数据
  • ICode国际青少年编程竞赛- Python-4级训练场-列表综合练习
  • 苹果电脑怎么安装crossover 如何在Mac系统中安装CrossOver CrossOver Mac软件安装说明
  • C++学习————第十天(string的基本使用)
  • 华为OD介绍
  • 判断点在多边形内部
  • livox雷达斜装修改
  • 【Spring】初识 Spring AOP(面向切面编程)
  • k8s各个组件的作用
  • Spring Cloud 整合Sentinel
  • Java入门基础学习笔记4——开发Helloworld入门程序
  • 了解WebSocket
  • 从开发角度理解漏洞成因(02)
  • Web实时通信的学习之旅:轮询、WebSocket、SSE的区别以及优缺点
  • TMS320F280049 CLB模块--LUT4 OUTLUT(4)
  • 功能测试_分类_用例_方法
  • [沫忘录]MySQL 锁
  • 噪声嵌入提升语言模型微调性能
  • XML文档基本语法