网站首页 > 博客文章 正文
前言
??在日常的工作中,为了提高程序的处理速度,充分利用多核处理器的性能,我们需要手动编写多线程代码。但是多线程编程非常复杂,容易出现死锁、竞态条件等问题,给我们带来了很大的困扰。而 Java 并行流则提供了一种更加简单、易用、安全的并发编程方式,可以让我们更加轻松地编写高效的并发程序。
使用多线程下载文件
public class MultiThreadExample {
public static void main(String[] args) throws InterruptedException {
List<String> urls = Arrays.asList(
"https://example.com/file1.txt",
"https://example.com/file2.txt",
"https://example.com/file3.txt",
"https://example.com/file4.txt",
"https://example.com/file5.txt"
);
int threads = 5;
int chunkSize = urls.size() / threads;
int startIndex = 0;
int endIndex = chunkSize;
// 创建线程列表
List<DownloadThread> downloadThreads = new ArrayList<>();
// 启动多个线程进行文件下载
for (int i = 0; i < threads; i++) {
downloadThreads.add(new DownloadThread(urls, startIndex, endIndex));
downloadThreads.get(i).start();
startIndex += chunkSize;
endIndex += chunkSize;
}
// 等待所有线程结束并汇总结果
for (DownloadThread downloadThread : downloadThreads) {
downloadThread.join();
}
System.out.println("文件下载完成");
}
}
class DownloadThread extends Thread {
private List<String> urls;
private int start;
private int end;
public DownloadThread(List<String> urls, int start, int end) {
this.urls = urls;
this.start = start;
this.end = end;
}
@Override
public void run() {
for (int i = start; i < end; i++) {
HttpUtil.download(urls.get(i));
}
}
}
??我们首先将要下载的文件 URL 存储在一个 List 中,然后为每个块创建了一个 DownloadThread 对象,并启动了多个线程进行下载操作。每个线程只负责处理 URL 的一个块,调用 HttpUtil.download 方法进行文件下载操作。最后,我们等待所有线程结束即可。
使用Fork/Join进行下载
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
public class ForkJoinExample {
public static void main(String[] args) {
List<String> urls = Arrays.asList(
"https://example.com/file1.txt",
"https://example.com/file2.txt",
"https://example.com/file3.txt",
"https://example.com/file4.txt",
"https://example.com/file5.txt"
);
ForkJoinPool pool = new ForkJoinPool();
pool.invoke(new DownloadAction(urls, 0, urls.size()));
System.out.println("文件下载完成");
}
static class DownloadAction extends RecursiveAction {
private List<String> urls;
private int start;
private int end;
public DownloadAction(List<String> urls, int start, int end) {
this.urls = urls;
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if (end - start <= 1) {
HttpUtil.download(urls.get(start));
return;
}
int mid = (start + end) / 2;
DownloadAction leftAction = new DownloadAction(urls, start, mid);
DownloadAction rightAction = new DownloadAction(urls, mid, end);
invokeAll(leftAction, rightAction);
}
}
}
??在这个示例中,我们使用了 ForkJoin 框架来实现文件下载。首先,我们创建了一个 DownloadAction 类,继承自 RecursiveAction 类,表示一个递归操作。在 compute 方法中,我们首先判断当前操作的 URL 是否为一个,如果是,则直接调用 HttpUtil.download 方法进行文件下载。如果不是,则将 URL 列表分为两半,分别创建两个子任务进行处理,然后使用 invokeAll 方法将这两个子任务提交到线程池中并等待它们完成。
??在 main 方法中,我们首先创建了一个 ForkJoinPool 对象,然后调用 invoke 方法来执行 DownloadAction 操作。在这里,我们使用了默认的线程池,也可以根据需要创建自定义的线程池。
使用Java并行流
import java.util.Arrays;
import java.util.List;
public class ParallelStreamExample {
public static void main(String[] args) {
List<String> urls = Arrays.asList(
"https://example.com/file1.txt",
"https://example.com/file2.txt",
"https://example.com/file3.txt",
"https://example.com/file4.txt",
"https://example.com/file5.txt"
);
urls.parallelStream().forEach(url -> HttpUtil.download(url));
System.out.println("文件下载完成");
}
}
??在这个示例中,我们使用了 Java 并行流来实现文件下载。首先,我们创建了一个 URL 列表,然后使用 parallelStream 方法将其转换为并行流。接着,我们使用 forEach 方法遍历并行流中的每个 URL,并使用 HttpUtil.download 方法进行文件下载。在这个过程中,Java 会自动将并行流中的元素分配给多个线程并行执行,以提高程序的性能。
Java 并行流是什么?
??好了,相信看了上面的案例,应该对并行流有了一个简单的认识了吧。让原本又丑又长的代码,一下就变得眉清目秀了。所以那让我们进一步的来了解它吧。
??Java 并行流是 Java 8 中新增的一个特性,它提供了一种便捷的方式来进行并发计算。在传统的 Java 编程中,为了利用多核处理器的性能,我们需要手动编写多线程代码。但是多线程编程非常复杂,容易出现死锁、竞态条件等问题,给我们带来了很大的困扰。而 Java 并行流则提供了一种更加简单、易用、安全的并发编程方式,可以让我们更加轻松地编写高效的并发程序。
??Java 并行流的核心是将数据集合分成多个小块,然后在多个处理器上并行处理,最后将结果合并成一个结果集。使用 Java 并行流可以有效地利用多核处理器的性能,提升程序运行效率。此外,Java 并行流还提供了一系列的中间操作和终止操作,可以方便地进行数据筛选、映射、过滤等操作。
Java并行流的实现原理?
??Java 并行流是基于 Fork/Join 框架实现的,它使用了多线程来处理流操作。具体来说,Java 并行流的实现原理如下:
- 拆分数据
??当并行流操作开始时,数据会被拆分成多个小块。每个小块都会被分配给不同的线程去处理。
- 执行任务
??每个线程会独立地执行任务。线程会使用 fork/join 框架将自己的任务拆分成更小的子任务,并将这些子任务分配给其他线程。
- 合并结果
??当所有线程完成任务后,它们会将自己的结果合并到一起。这个过程类似于 reduce 操作,不同之处在于它是并行的。
??Java 并行流的是基于 Fork/Join 框架实现的,而Fork/Join 框架是 Java 7 引入的一个用于并行计算的框架,它基于工作窃取算法,可以将一个大任务拆分成多个小任务,每个线程独立地处理一个小任务。在 Java 8 中,通过对 Stream 接口的扩展,使得并行计算更加容易实现。
??需要注意的是,Java 并行流在执行操作时,会根据当前计算机的 CPU 核心数来确定并行线程的数量,如果并行线程数量过多,会造成过多的上下文切换,反而会降低程序的性能。因此,在使用并行流时需要注意控制并行线程的数量。
三种方式对比
?? 在文件下载这个例子中,我们使用了多线程、ForkJoin 框架和 Java 并行流三种方式来实现。我们来对比一下这三种方式的优缺点。
1. 多线程方式
优点:
- 可以手动控制线程的数量,适用于对线程数量有特殊要求的场景。
- 可以使用线程池来重用线程,减少线程创建和销毁的开销。
- 可以使用 wait 和 notify 等机制来实现线程间的通信和协作。
缺点:
- 需要手动编写线程的创建和销毁代码,代码复杂度较高。
- 线程之间的协作和通信需要手动实现,容易出现死锁等问题。
- 代码的可读性和可维护性较差。
2. ForkJoin 框架方式
优点:
- 可以自动地将任务拆分成更小的子任务,并将子任务分配给多个线程并行执行,简化了代码实现。
- 可以通过调整并行度来优化性能,提高代码的灵活性。
- 可以使用默认的线程池或自定义的线程池来管理线程。
缺点:
- 不适用于 IO 密集型操作,仅适用于 CPU 密集型操作。
- 线程之间的协作和通信需要手动实现,容易出现死锁等问题。
3. Java 并行流方式
优点:
- 可以使用函数式编程的方式简化代码实现,代码可读性较高。
- 可以自动地将数据分配给多个线程并行处理,简化了代码实现。
- 可以根据需要选择并行度来优化性能。
- 可以通过流水线方式优化代码性能,提高代码的灵活性。
缺点:
- 不适用于 IO 密集型操作,仅适用于 CPU 密集型操作。
- 对于一些特殊的操作,例如排序和去重,可能需要手动调整代码才能使用并行流。
总结
??Java并行流可以让多线程编程变得更加简单易懂,减少编程中的并发问题,提高代码质量和可维护性。帮助开发人员更加轻松地实现任务并行,充分利用多核处理器的性能,加快程序的执行速度。但是虽然并行流有诸多优点,但是还需要根据具体场景来选择合适的方式。如果是 IO 密集型操作,我们应该使用多线程或者 Java NIO 等技术来实现;如果是 CPU 密集型操作,我们可以使用 ForkJoin 框架或者 Java 并行流来实现。
结尾
??如果觉得对你有帮助,可以多多评论,多多点赞哦,也可以到我的主页看看,说不定有你喜欢的文章,也可以随手点个关注哦,谢谢。
??我是不一样的科技宅,每天进步一点点,体验不一样的生活。我们下期见!
- 上一篇: 面渣逆袭:二十二图、八千字、二十问,彻底搞定MyBatis
- 下一篇: 【一分钟学Java】之List
猜你喜欢
- 2024-12-26 Java 8 Stream 处理大数据集:实战与优化
- 2024-12-26 面试官:Java8 lambda 表达式 forEach 如何提前终止?
- 2024-12-26 Javascript中,forEach和map到底有什么区别?
- 2024-12-26 Excel VBA之For Each遍历循环的应用
- 2024-12-26 为什么建议使用 for…of 循环而不是 foreach 循环呢
- 2024-12-26 前端开发map和foreach区别,map遍历方式用法介绍
- 2024-12-26 Rust语言从入门到精通系列 - 零基础掌握Stream流迭代器
- 2024-12-26 Map遍历的四种方法效率对比
- 2024-12-26 java集合类之java中集合类有哪些?如何分类?
- 2024-12-26 【一分钟学Java】之List
你 发表评论:
欢迎- 最近发表
-
- 给3D Slicer添加Python第三方插件库
- Python自动化——pytest常用插件详解
- Pycharm下安装MicroPython Tools插件(ESP32开发板)
- IntelliJ IDEA 2025.1.3 发布(idea 2020)
- IDEA+Continue插件+DeepSeek:开发者效率飙升的「三体组合」!
- Cursor:提升Python开发效率的必备IDE及插件安装指南
- 日本旅行时想借厕所、买香烟怎么办?便利商店里能解决大问题!
- 11天!日本史上最长黄金周来了!旅游万金句总结!
- 北川景子&DAIGO缘定1.11 召开记者会宣布结婚
- PIKO‘PPAP’ 洗脑歌登上美国告示牌
- 标签列表
-
- ifneq (61)
- messagesource (56)
- aspose.pdf破解版 (56)
- promise.race (63)
- 2019cad序列号和密钥激活码 (62)
- window.performance (66)
- qt删除文件夹 (72)
- mysqlcaching_sha2_password (64)
- ubuntu升级gcc (58)
- nacos启动失败 (64)
- ssh-add (70)
- jwt漏洞 (58)
- macos14下载 (58)
- yarnnode (62)
- abstractqueuedsynchronizer (64)
- source~/.bashrc没有那个文件或目录 (65)
- springboot整合activiti工作流 (70)
- jmeter插件下载 (61)
- 抓包分析 (60)
- idea创建mavenweb项目 (65)
- vue回到顶部 (57)
- qcombobox样式表 (68)
- vue数组concat (56)
- tomcatundertow (58)
- pastemac (61)
本文暂时没有评论,来添加一个吧(●'◡'●)