给定一个int数组,假设有10000个长度,里面放满1-100的随机整数。需要用串行循环计算、Executors框架和Fork-Join框架三种方法,实现查找并输出该数组中50的出现个数。
提交源程序和和执行结果截图。
预期执行结果如下(具体数量根据每个程序随机赋值决定)
串行搜索得到50的个数是5个。
Executors搜索得到50的个数是5个。
Fork-Join搜索得到50的个数是5个。
import java.util.concurrent.*;
public class FindNumberCount {
public static void main(String[] args) throws InterruptedException, ExecutionException {
int[] numbers = new int[100450];
int targetNumber = 50;
for (int i = 0; i < numbers.length; i++) {
numbers[i] = (int) (Math.random() * 100);
}
System.out.println("findBySerial = " + findBySerial(numbers, targetNumber));
System.out.println("findByExecutor = " + findByExecutor(numbers, targetNumber));
System.out.println("findByForkJoin = " + findByForkJoin(numbers, targetNumber));
}
public static int findBySerial(int[] numbers, int targetNumber) {
int cnt = 0;
for (int i = 0; i < numbers.length; i++) {
if (numbers[i] == targetNumber)
cnt++;
}
return cnt;
}
public static int findByExecutor(int[] numbers, int targetNumber) throws InterruptedException {
ExecutorService executor = Executors.newCachedThreadPool();
int increment = 1000; //每1000长度为一组
int numOfThread = numbers.length / increment;
CountDownLatch latch = new CountDownLatch(numOfThread);
int startIndex = 0, endIndex = increment - 1;
for (int i = 0; i < numOfThread; i++) {
if (i == numOfThread - 1)
endIndex = numbers.length - 1;
executor.execute(new ExecutorTask(numbers, startIndex, endIndex, targetNumber, latch));
// new Thread(new ExecutorTask(numbers, startIndex, endIndex, targetNumber, latch)).start();
startIndex = endIndex + 1;
endIndex = endIndex + increment;
}
latch.await();
executor.shutdown();
return ExecutorTask.getSumCnt();
}
public static int findByForkJoin(int[] numbers, int targetNumber) throws InterruptedException, ExecutionException {
ForkJoinPool pool = new ForkJoinPool();
ForkJoinTask<Integer> task = new MyForkJoinTask(numbers, 0, numbers.length - 1, targetNumber);
task = pool.submit(task);
Integer cnt = task.get();
pool.shutdown();
return cnt;
}
}
class ExecutorTask implements Runnable {
private static int sumCnt = 0;
private int[] numbers;
private int startIndex;
private int endIndex;
private int targetNumber;
private CountDownLatch latch;
public ExecutorTask(int[] numbers, int startIndex, int endIndex, int targetNumber, CountDownLatch latch) {
this.numbers = numbers;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.targetNumber = targetNumber;
this.latch = latch;
}
@Override
public void run() {
int cnt = 0;
for (int i = startIndex; i <= endIndex; i++) {
if (numbers[i] == targetNumber)
cnt++;
}
synchronized (ExecutorTask.class) {
sumCnt += cnt;
}
latch.countDown();
}
public static int getSumCnt() {
return sumCnt;
}
}
class MyForkJoinTask extends RecursiveTask<Integer> {
int[] numbers;
int startIndex;
int endIndex;
int targetNumber;
public MyForkJoinTask(int[] numbers, int startIndex, int endIndex, int targetNumber) {
this.numbers = numbers;
this.startIndex = startIndex;
this.endIndex = endIndex;
this.targetNumber = targetNumber;
}
@Override
protected Integer compute() {
int cnt = 0;
if (endIndex - startIndex < 1000) {
for (int i = startIndex; i <= endIndex; i++) {
if (numbers[i] == targetNumber)
cnt++;
}
} else {
int midIndex = (startIndex + endIndex) / 2;
MyForkJoinTask leftTask = new MyForkJoinTask(numbers, startIndex, midIndex, targetNumber);
MyForkJoinTask rightTask = new MyForkJoinTask(numbers, midIndex + 1, endIndex, targetNumber);
// leftTask.fork();
// cnt = rightTask.compute() + leftTask.join();
invokeAll(leftTask, rightTask);
cnt = rightTask.join() + leftTask.join();
}
return cnt;
}
}