目录
项目场景
问题描述
解决方案:
方法一:没有返回值,直接在任务里完成计算
方法二:有返回值
最后
项目场景
前台通过模板批量上传数据到后台
问题描述
后台使用常规方法处理数据,效率低下
解决方案:
使用多线程线程池实现
方法一:没有返回值,直接在任务里完成计算
package com.lwk.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class ThreadPoolExample {
public static void main(String[] args) throws InterruptedException {
// 创建一个包含 10 个线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 创建一个包含 10000 个元素的 List
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10001; i++) {
list.add(i);
}
// 将 List 分成 10 个子 List,每个子 List 包含 1000 个元素
List<List<Integer>> subLists = new ArrayList<>();
int subListSize = 1000;
for (int i = 0; i < list.size(); i += subListSize) {
subLists.add(list.subList(i, Math.min(i + subListSize, list.size())));
}
// 提交每个子 List 的处理任务给线程池
for (List<Integer> subList : subLists) {
executorService.submit(new Task(subList));
}
// 等待线程池中所有任务执行完毕
executorService.shutdown();
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
// 打印处理结果
System.out.println("List size: " + list.size());
System.out.println("Sum of elements: " + Task.getSum());
}
static class Task implements Runnable {
private List<Integer> list;
private static long sum = 0;
public Task(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
long subSum = 0;
for (int i : list) {
subSum += i;
}
synchronized (Task.class) {
sum += subSum;
}
}
public static long getSum() {
return sum;
}
}
}
方法二:有返回值
除了创建线程池和分割 List 的过程外,主要的变化是将 Task 类改为实现 Callable 接口,并返回子 List 的和。使用 CompletionService 提交任务和获取任务执行结果,从而减少了线程池的等待时间,提高了执行效率。最后,将每个子 List 的和累加起来,打印处理结果。
package com.lwk.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.*;
public class ThreadPoolExample2 {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建一个包含 10 个线程的线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
// 创建一个 CompletionService,用于提交任务和获取任务执行结果
CompletionService<Long> completionService = new ExecutorCompletionService<>(executorService);
// 创建一个包含 10000 个元素的 List
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 10001; i++) {
list.add(i);
}
// 将 List 分成 10 个子 List,每个子 List 包含 1000 个元素
List<List<Integer>> subLists = new ArrayList<>();
int subListSize = 1000;
for (int i = 0; i < list.size(); i += subListSize) {
subLists.add(list.subList(i, Math.min(i + subListSize, list.size())));
}
// 提交每个子 List 的处理任务给 CompletionService
for (List<Integer> subList : subLists) {
completionService.submit(new Task(subList));
}
// 获取每个任务的执行结果,并将结果累加起来
long sum = 0;
for (int i = 0; i < subLists.size(); i++) {
Future<Long> future = completionService.take();
sum += future.get();
}
// 打印处理结果
System.out.println("List size: " + list.size());
System.out.println("Sum of elements: " + sum);
// 关闭线程池
executorService.shutdown();
}
static class Task implements Callable<Long> {
private List<Integer> list;
public Task(List<Integer> list) {
this.list = list;
}
@Override
public Long call() throws Exception {
long subSum = 0;
for (int i : list) {
subSum += i;
}
return subSum;
}
}
}
最后
如果改为项目中使用的话,需要将 【创建一个包含 10000 个元素的 List】改为自己的数据集即可!
需要注意的是:在使用线程池时,需要选择合适的线程池大小,以避免创建过多的线程导致系统资源耗尽!
还有一点:也不要盲目的去开多个线程。如果你的服务器是单cpu单核开多线程反而会增加上下文损耗,从而降低程序执行效率。能开多少个线程,理论是这样计算的:逻辑cpu个数 = (物理cpu个数 * 每个cpu的核心数 * 超线程数),命令见如下:
1.查看物理cpu个数,也就是实物cpu的个数
cat /proc/cpuinfo| grep "physical id"| sort| uniq| wc -l
2.查看每个cpu的core,也就是常说的核心数
cat /proc/cpuinfo| grep "cpu cores"| uniq文章来源:https://www.toymoban.com/news/detail-482943.html
今天的分享就到这里了,如果问题欢迎留言指正! 文章来源地址https://www.toymoban.com/news/detail-482943.html
到了这里,关于java多线程处理list,速度提升嗖嗖的!的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!