- 首先确定线程数量。如果数据集合的大小小于50,就只使用一个线程;否则使用5个线程。
- 计算每个线程平均处理的数据数量
sizePerThread
以及余数remainder
。 - 在划分数据子集合时,对于每个线程的处理范围进行计算。如果有余数,就将余数依次分配到前面的线程中(这里是简单地让前面的线程多处理一个数据)。
- 最后一个线程的结束索引直接设置为数据集合的大小,确保能处理完所有数据。
- 每个线程在处理完自己的数据后,调用
latch.countDown()
,主线程通过latch.await()
等待所有线程完成任务后,再继续执行后续操作。 CopyOnWriteArrayList
,它是线程安全的,适用于读多写少的场景
package com.syplatform;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import org.junit.Test;
/**
* Unit test for simple App.
*/
public class AppTest {
/**
* Rigorous Test :-)
*/
@Test
public void shouldAnswerWithTrue() throws InterruptedException {
CopyOnWriteArrayList<Integer> finalList = new CopyOnWriteArrayList<>();
List<Integer> dataList = new ArrayList<>();
for (int i = 1; i <= 101; i++) {
dataList.add(i);
}
// 根据数据量决定线程数量
int numThreads = dataList.size() < 50 ? 1 : 5;
int size = dataList.size();
int partSize = size / numThreads;
// 处理不能整除的情况,将剩余的任务分配到前面的线程中
int remainder = size % numThreads;
int startIndex = 0;
CountDownLatch latch = new CountDownLatch(numThreads);
for (int i = 0; i < numThreads; i++) {
int endIndex = startIndex + partSize + (i < remainder ? 1 : 0);
List<Integer> subList = dataList.subList(startIndex, endIndex);
startIndex = endIndex;
Thread thread = new Thread(() -> {
for (Integer num : subList) {
finalList.add(num);
System.out.println(Thread.currentThread().getName() + " processing " + num);
}
latch.countDown();
});
thread.start();
}
latch.await();
System.out.println("All threads have finished processing.");
assertTrue(finalList.size() == 101);
}
}