利用多线程输出1-10000的素数的个数

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u010285684/article/details/87928570

1. 使用技术

  • jdk1.8
  • idea2018.3.4

2. 涉及到的线程主要的类

  1. Executors
  • 此包java.util.concurrent中定义的Executor,ExecutorService,ScheduledExecutorService,ThreadFactory和Callable类的工厂和实用程序方法。 该类支持以下几种方法:
    创建和返回ExecutorService的方法,使用常用的配置设置进行设置。
    创建和返回ScheduledExecutorService的方法,使用常用的配置设置进行设置。
    创建并返回“包装”ExecutorService的方法,通过使特定于实现的方法不可访问来禁用重新配置。
    创建并返回ThreadFactory的方法,该ThreadFactory将新创建的线程设置为已知状态。
    从其他类似闭包形式创建和返回Callable的方法,因此可以在需要Callable的执行方法中使用它们。
  1. ExecutorService
  • 继承 Executor 执行者
  • 一个Executor(执行者),提供管理终止的方法和可以生成Future以跟踪一个或多个异步任务进度的方法。
    可以关闭ExecutorService,这将导致它拒绝新任务。提供了两种不同的方法来关闭ExecutorService。 shutdown方法将允许先前提交的任务在终止之前执行,而shutdownNow方法则阻止等待任务启动并尝试停止当前正在执行的任务。终止时,执行程序没有正在执行的任务,没有等待执行的任务,也没有任何新任务可以提交。应关闭未使用的ExecutorService以允许回收其资源。
    方法提交通过创建和返回可用于取消执行和/或等待完成的Future来扩展基本方法Executor.execute(Runnable)。方法invokeAny和invokeAll执行最常用的批量执行形式,执行一组任务,然后等待至少一个或全部完成。 (类ExecutorCompletionService可用于编写这些方法的自定义变体。)
    Executors类为此包中提供的执行程序服务提供工厂方法。
  1. ForkJoinPool
  • 体现一个分而治之的思想,其实就是递归算法
  • 开启一个新线程(或是重用线程池内的空闲线程),将任务交给该线程处理, 等待该任务的处理线程处理完毕,获得返回值。

3. 涉及的主要的方法

  1. Executors#newWorkStealingPool() :创建一个和主机核心数量一样多的线程池,使用所有可用处理器作为其目标并行度级别创建工作窃取线程池。
  2. ExecutorService#invokeAll() : 执行给定的任务,返回完成所有状态和结果的Futures列表。 对于返回列表的每个元素,Future.isDone都为true。 请注意,已完成的任务可能正常终止或通过抛出异常终止。 如果在此操作正在进行时修改了给定集合,则此方法的结果是不确定的。

4. 代码的实现

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * 输出范围内1-10000的素数的个数
 * {@link Executors} : 提供了方便的工厂方法来创建不同类型的执行程序服务.其实就是创建线程池
 * {@link ExecutorService} : 执行线程池的执行器。
 * {@link Executors#newWorkStealingPool()} : 默认是创建主机CPU的可用核心数线程池
 */
public class PrimeCalculationApp {
    public static void main(String[] args) throws InterruptedException {
        // 1.线程服务提供者(线程池大小与主机核心默认是一样的)
        ExecutorService executor = Executors.newWorkStealingPool();
        // 2.可回调的线程的列表
        PrimeCalculationThread server1 = new PrimeCalculationThread(1, 2500);
        PrimeCalculationThread server2 = new PrimeCalculationThread(2501, 5000);
        PrimeCalculationThread server3 = new PrimeCalculationThread(5001, 7500);
        PrimeCalculationThread server4 = new PrimeCalculationThread(7501, 10000);
        List<Callable<Integer>> list = Arrays.asList(server1, server2, server3, server4);
        // 3.批量执行所有的线程
        Integer collect = executor.invokeAll(list)
                .stream()
                .map(future -> {
                    Integer sum = 0;
                    try {
                        sum = future.get();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    } catch (ExecutionException e) {
                        e.printStackTrace();
                    }
                    return sum;
                }).collect(Collectors.summingInt(Integer::intValue));
        System.out.println("素数的数量 : " + collect);
    }
}

/**
 * 范围内(列如小于等于1000)的多线程计算素数的方法
 */
class PrimeCalculationThread implements Callable<Integer> {
    private int start;
    private int end;

    public PrimeCalculationThread(int start, int end) {
        this.start = start;
        this.end = end;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        int j;
        for (int i = start; i <= end; i++) {
            j = 2;
            for (; j <= Math.sqrt(i); j++) {
                if (i % j == 0) {
                    break;
                }
            }
            if (j > Math.sqrt(i)) {
                // System.out.println(i);
                sum++;
            }
        }
        return sum;
    }
}

猜你喜欢

转载自blog.csdn.net/u010285684/article/details/87928570