场景
面对一个10000个元素的随机数数组,使用线程池进行多线程求和。
思路
可以开一个容量为10的线程池,将10000个元素分成10个区间,每个线程负责一段区间。具体写法有两种。
法一
- 每个线程都有返回值,代表所负责的那段区间的元素和,在主线程中拿到每个线程负责的元素和,然后相加得到结果。
代码
import java.util.Random;
import java.util.concurrent.*;
public class ThreadPoolDemo2 {
public int getNumsum(int index,int[] nums){
int numsum=0;
for(int i=index;i<index+1000;++i){
numsum+=nums[i];
}
return numsum;
}
public static void main(String[] args) throws ExecutionException, InterruptedException, TimeoutException {
ThreadPoolDemo2 threadPoolDemo2=new ThreadPoolDemo2();
int n=10000;
int[] nums=new int[n];
Integer trueans=0;
Integer countnum=0;
for(int i=0;i<n;++i){
int num= new Random().nextInt(100);
nums[i]=num;
trueans+=num;
}
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(
10,20,5, TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
for(int i=0;i<10;++i){
final int index=i;
Future<Integer> td = threadPoolExecutor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return threadPoolDemo2.getNumsum(index*1000,nums);
}
});
countnum+=td.get();
}
threadPoolExecutor.shutdown();
System.out.println("真实和:"+trueans);
System.out.println("多线程和:"+countnum);
}
}
法二
- 一个全局变量保存结果,每个线程都操作这个全局变量。这样的话很明显会出现线程安全问题,加锁呢又不合适,都使用线程池了不就是寻求并行操作吗,那加锁就不合适了。这里因为操作的是一个变量因此可以使用原子变量去解决。底层是CAS,但也不是真正的并行,总体来说还是法一好。
代码
import java.util.Random;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
public class ThreadPoolDemo {
volatile AtomicInteger numsum=new AtomicInteger();
public void getNumsum(int index,int[] nums){
for(int i=index;i<index+1000;++i){
numsum.addAndGet(nums[i]);
}
}
public static void main(String[] args) throws InterruptedException {
ThreadPoolDemo demo=new ThreadPoolDemo();
int n=10000;
int[] nums=new int[n];
int trueans=0;
for(int i=0;i<n;++i){
int num= new Random().nextInt(100);
nums[i]=num;
trueans+=num;
}
ThreadPoolExecutor tpe=new ThreadPoolExecutor(
10,
20,
5,
TimeUnit.SECONDS,
new ArrayBlockingQueue<>(10),
Executors.defaultThreadFactory(),
new ThreadPoolExecutor.AbortPolicy()
);
for(int i=0;i<10;++i){
final int idx=i;
tpe.execute(new Runnable() {
@Override
public void run() {
demo.getNumsum(idx*1000,nums);
}
});
}
tpe.shutdown();
Thread.sleep(300);//这里要延时一下,防止线程还没结束就输出了。
System.out.println("真实和:"+trueans);
System.out.println("多线程和:"+demo.numsum);
}
}