【多线程开发 1】从多线程读取文件开始实践多线程开发

embedded/2024/10/22 4:51:11/

2024年5月3日

今天心情不错,写一篇多线程开发的文章过过瘾。 话不多说,问题如下

利用多线程读取文件中的所有单词,统计每个单词出现的次数。

一看就知道问题很简单,话不多说代码如下,其中的很多代码我们都会一个一个的解析

java">    public static void main(String[] args) throws FileNotFoundException {ThreadPoolExecutor executorService = new ThreadPoolExecutor(20,  // 核心线程数量20,              //最大线程数60,             //空闲临时线程最大存活时间(数值)TimeUnit.SECONDS,//空闲临时线程最大存活时间(单位)new ArrayBlockingQueue<>(1_000_000_00),//任务队列,也就是一个堵塞队列,也可以使用LinkedBlockingQueue这个阻塞队列Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个,丢弃任务并抛出RejectedExecutionException);Map<String, Integer> hashMap = new HashMap<>();File file = new File("C:\Users\Desktop\the_text_book.txt");System.out.println(executorService.getActiveCount());try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {String line;while ((line = bufferedReader.readLine()) != null) {String[] s = line.split(" ");if (s.length == 0) {continue;}executorService.submit(() -> {List<String> results = Arrays.asList(s);results.forEach(x -> {if (!(Objects.equals(x, "") || x == null)) {if (hashMap.containsKey(x)) {hashMap.put(x, hashMap.get(x) + 1);} else {hashMap.put(x, 1);}}});});}} catch (Exception e) {e.printStackTrace();}while (true) {if (executorService.getActiveCount() == 0) {hashMap.forEach((k, v) -> {System.out.println(k + " " + v);});executorService.shutdown();break;}}}

创建线程池

java">ThreadPoolExecutor executorService = new ThreadPoolExecutor(20,  // 核心线程数量20,              //最大线程数60,             //空闲临时线程最大存活时间(数值)TimeUnit.SECONDS,//空闲临时线程最大存活时间(单位)new ArrayBlockingQueue<>(1_000_000_00),//任务队列,也就是一个堵塞队列,也可以使用LinkedBlockingQueue这个阻塞队列Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个,丢弃任务并抛出RejectedExecutionException);

如果你已经是一名稍微有点年头的开发者,你肯定知道怎么写创建线程池的。说句题外话,如果是使用的把配置信息交给框架自动配置的开发者,可以将线程池也放到组件容器中,比如Spring框架就可以这么用。

获取输出结果

java">        while (true) {if (executorService.getActiveCount() == 0) {hashMap.forEach((k, v) -> {System.out.println(k + " " + v);});executorService.shutdown();break;}}

因为使用了线程池,所以如果需要查看最后的效果,我可能会这么写:最后写一个while循环阻塞掉主线程,知道拿到对应结果(使用的是自定义线程池的API)

如果不想阻塞主线程,可以尝试使用别的方式,比如说使用Java8的API,CompletableFuture类进行实现,这个有一个方式是*allOf() *,该方法可以做到让全部的CompletableFuture任务都完成后再进行后续输出,笔者认为这个是通过创建一个异步线程/子线程来专门用于某一行代码的实现,就可以不使用阻塞线程的代码了,实现的代码如下:

java">                // 创建CompletableFuture,并将任务提交给线程池futureList.add(CompletableFuture.supplyAsync(() -> {List<String> results = Arrays.asList(s);results.forEach(x -> {if (!(Objects.equals(x, "") || x == null)) {if (hashMap.containsKey(x)) {hashMap.put(x, hashMap.get(x) + 1);} else {hashMap.put(x, 1);}}});return null;}, executorService));}CompletableFuture.allOf(futureList.toArray(futureList.toArray(new CompletableFuture[0]))).whenComplete((v, th) -> {hashMap.forEach((k, value) -> {System.out.println(k + " " + value);});}).join();

这样就可以在不阻塞主线程的情况下实现效果了

不过有一件事我也不是很明白,交给阅读这篇文章的你,我使用了ConcurrentHashMap和不使用ConcurrentHashMap的情况下,效果一样没有问题,在写这篇文章的时候我也一直没搞明白<3;

希望能对你有所帮助;

最终代码

偶对了,为了方便大家直接使用我就把代码直接完全贴一份到博客里面吧

java">​public static void main(String[] args) throws FileNotFoundException {ThreadPoolExecutor executorService = new ThreadPoolExecutor(20,  // 核心线程数量20,              //最大线程数60,             //空闲临时线程最大存活时间(数值)TimeUnit.SECONDS,//空闲临时线程最大存活时间(单位)new ArrayBlockingQueue<>(1_000_000_00),//任务队列,也就是一个堵塞队列,也可以使用LinkedBlockingQueue这个阻塞队列Executors.defaultThreadFactory(),//用线程池工具类Executors创建线程的工厂new ThreadPoolExecutor.AbortPolicy()//任务的拒绝策略中其中一个,丢弃任务并抛出RejectedExecutionException);Map<String, Integer> hashMap = new ConcurrentHashMap<>();File file = new File("C:\Users\Desktop\the_text_book.txt");System.out.println(executorService.getActiveCount());List<CompletableFuture> futureList = new ArrayList<>();try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {String line;while ((line = bufferedReader.readLine()) != null) {String[] s = line.split(" ");if (s.length == 0) {continue;}// 创建CompletableFuture,并将任务提交给线程池futureList.add(CompletableFuture.supplyAsync(() -> {List<String> results = Arrays.asList(s);results.forEach(x -> {if (!(Objects.equals(x, "") || x == null)) {if (hashMap.containsKey(x)) {hashMap.put(x, hashMap.get(x) + 1);} else {hashMap.put(x, 1);}}});return null;}, executorService));}CompletableFuture.allOf(futureList.toArray(futureList.toArray(new CompletableFuture[0]))).whenComplete((v, th) -> {hashMap.forEach((k, value) -> {System.out.println(k + " " + value);});}).join();} catch (Exception e) {e.printStackTrace();}}

http://www.ppmy.cn/embedded/30668.html

相关文章

8.k8s中网络资源service

目录 一、service资源概述 二、service资源类型 1.ClusterIP类型 2.service的nodeport类型 3.service的loadbalancer类型&#xff08;了解即可&#xff09; 4.service的externalname类型&#xff08;了解即可&#xff09; 三、nodeport的端口范围设置和svc的endpoint列表 1.修…

【QT学习】13.使用TCP实现文件传输

一。传输文件流程 二。实现 结果&#xff1a; 1. server server类属性 Ui::Widget *ui;QTcpServer* pTcpServer;QTcpSocket* pTcpSocket;//文件与文件信息QFile file;QString m_fileName;qint64 m_fileSize; //整个文件大小qint64 fileSize; //当前已经发送的文件大小bool …

CSS中文本样式(详解网页文本样式)

目录 一、Text介绍 1.概念 2.特点 3.用法 4.应用 二、Text语法 1.文本格式 2.文本颜色 3.文本的对齐方式 4.文本修饰 5.文本转换 6.文本缩进 7.color&#xff1a;设置文本颜色。 8.font-family&#xff1a;设置字体系列。 9.font-size&#xff1a;设置字体大小。…

真机无需root实现抓包的两种方式之一小黄鸟篇

最新买了一部vivo Y30手机(V2034,android版本10,内存8G,存储128G)。 pc环境:win10,python3.8.10。 目的:实现vivo Y30上浏览器以及各类APP的https抓包。 众所周知,在Andorid7(含)以上系统内抓包,需要root环境,将https证书从用户证书转移到系统证书中来,在没有…

高德地图在vue3项目中使用:实现画矢量图、编辑矢量图

使用高德地图实现画多边形、矩形、圆&#xff0c;并进行编辑保存和回显。 1、准备工作 参考高德地图官网&#xff0c;进行项目key申请&#xff0c;链接: 准备 2、项目安装依赖 npm i amap/amap-jsapi-loader --save3、地图容器 html <template><!-- 绘制地图区域…

课程35:Docker容器:Windows Containers与Linux Containers区别

这里写目录标题 🚀前言一、Windows Containers与Linux Containers区别二、基于Linux本地Docker调试2.1 添加Docker支持2.2 Windows与Linux本地Docker调试的区别2.2.1 对比不同目标OS2.2.2 Dockerfile区别2.2.3 项目文件2.3 总结三、Windows下基于Linux Containers部署3.1 发布…

快讯! MySQL 8.4.0 LTS 发布(MySQL 第一个长期支持版本)

MySQL 第一个长期支持版本 8.4.0 LTS 发布&#xff0c;社区版下载地址&#xff1a; https://dev.mysql.com/downloads/mysql/ 功能变更 添加或更改的功能 组复制&#xff1a;与组复制相关的两个服务器系统变量的默认值已更改&#xff1a; 系统变量的默认值为 group_replication…

《Spring-MVC》系列文章目录

简介 Spring MVC是一种基于Java的实现MVC设计模式的请求驱动类型的轻量级Web框架&#xff0c;它通过把Model&#xff08;模型&#xff09;、View&#xff08;视图&#xff09;、Controller&#xff08;控制器&#xff09;分离&#xff0c;将web层进行职责解耦&#xff0c;把复杂…