【Java】将一个List拆分使用线程池多线程运行
需求:
将点位List(pointList)分成每100个点为一组,循环每一组,每组开启100个线程进行获取数据,且前一组100个线程执行完毕后才进行下一组。
// 将list分割成每100个为一个子列表
List<List<DynaBean>> subLists = splitListIntoChunks(pointList, THREAD_POOL_SIZE);
for (List<DynaBean> subList : subLists) {
// 创建一个Future集合来保存所有的Future对象
List<Future<?>> futures = new ArrayList<>();
/**
* 创建一个固定大小的线程池。
* 线程池的大小被设置为THREAD_POOL_SIZE,这个大小是根据预先定义好的常量来确定的。
* 这样做的目的是为了限制同时执行的任务数量,避免过多的任务导致系统资源耗尽。
*/
ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);
/**
* 创建一个计数器 latch,其计数初始值为subList.size()。
* 这个 latch 的作用是用于等待所有线程任务完成。
* 当线程池中的每个线程任务完成时,latch 的计数器会递减。
* 当计数器减到0时,表示所有线程任务都已完成,此时主程序可以继续执行。
*/
CountDownLatch latch = new CountDownLatch(subList.size());
for(DynaBean bean : subList){
Future<?> future = executor.submit(() -> {
try{
//do something
}finally {
latch.countDown();
}
});
futures.add(future);
}
// 等待所有任务完成
for (Future<?> future : futures) {
try {
future.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("Error processing tasks", e);
}
}
// 关闭线程池
executor.shutdown();
latch.await();
}
/**
* 将一个DynaBean列表分割成多个指定大小的块。
* 这个方法用于将一个大列表分解成多个小列表,每个小列表的大小不超过指定的块大小。
* 如果最后一个块的大小小于指定的块大小,则该块将包含列表的剩余元素。
*
* @param list 待分割的DynaBean列表。
* @param chunkSize 每个块的目标大小。
* @return 一个包含分割后的DynaBean列表的列表。
*/
private static List<List<DynaBean>> splitListIntoChunks(List<DynaBean> list, int chunkSize) {
if (chunkSize <= 0) {
throw new IllegalArgumentException("Chunk size must be positive.");
}
List<List<DynaBean>> chunks = new ArrayList<>();
final int totalChunks = (int) Math.ceil((double) list.size() / chunkSize);
for (int i = 0; i < totalChunks; i++) {
int start = i * chunkSize;
int end = Math.min(start + chunkSize, list.size());
chunks.add(new ArrayList<>(list.subList(start, end)));
}
return chunks;
}