Java 多线程进阶-并发编程(二) Executor Framework(JDK5以上)

  • Executor(1)

    • 从JDK5 开始提供Executor FrameWork(java.util.concurrent.*)
      • 分离任务和创建和执行者的创建
      • 线程重复利用(new线程代价很大)
    • 理解共享线程池的概念
      • 预设好的多个Thread, 可弹性增加
      • 多次执行很多很小的任务
      • 任务创建和执行过程解耦
      • 程序猿无需关心线程池执行任务过程
  • Executor(2)

    • 主要类: ExecutorService, ThreadPoolExecutor, Future
      • Executors.newCachesThreadPool/newFixedThreadPool 创建线程池
      • ExecutorService 线程池服务
      • Callable 具体的逻辑对象(线程类),
        Callable 和 Runnable 是等价的, 可以用来执行一个任务.
        Runnable 的 run 方法没有返回值;
        Callable 的 call 方法可以有返回值.
      • Future 返回结果
    • 示例代码
          package thread0411;
      
          import java.time.LocalDateTime;
          import java.util.ArrayList;
          import java.util.List;
          import java.util.Random;
          import java.util.concurrent.*;
      
          /**
           * 分多个线程, 分段计算两个数字之间累加的和.
           * 1-1000的和 = 1-100的和 + 101-200的和 + ...
           */
          public class ThreadPool_Executor2 {
      
              public static void main(String[] args) {
      
      
                  long m = 1;
                  long n = 1000; //100000000
      
                  // 执行线程池
                  ThreadPoolExecutor exec = (ThreadPoolExecutor) Executors.newFixedThreadPool(4);
      
                  List<Future<Integer>> resultList = new ArrayList<>();
                  // 统计 1-1000 的总和, 分成10个任务去计算, 提交任务
                  long section = n / 10;
                  for (int i = 0; i < 10; i++) {
                      SumTask111 calc = new SumTask111(i * section + 1, (i + 1) * section);
                      Future<Integer> re = exec.submit(calc);
                      resultList.add(re);
                  }
      
                  // 每隔50毫秒, 轮询查询一下是否全部完成.
                  // 等待10个任务结束
                  do {
                      System.out.printf(LocalDateTime.now() + " => " + "Main: 已经完成任务个数: %d" + "\n", exec.getCompletedTaskCount());
          //            for (int i = 0; i < resultList.size(); i++) { // 输出一下任务是否完成
          //                Future<Integer> re = resultList.get(i);
          //                System.out.printf(LocalDateTime.now() + " => " + "Main: Task %d: %s" + "\n", i, re.isDone());
          //            }
                      try {
                          Thread.sleep(50); // 过 50ms 再检查一下是否全部完成.
                      } catch (InterruptedException e) {
                          e.printStackTrace();
                      }
                  } while (exec.getCompletedTaskCount() < resultList.size());
      
                  // 所有任务都已经结束了, 综合计算结果
                  int total = 0;
                  for (Future<Integer> result : resultList) {
                      Integer sum;
                      try {
                          sum = result.get();
                          total += sum;
                      } catch (InterruptedException | ExecutionException e) {
                          e.printStackTrace();
                      }
                  }
                  System.out.printf(LocalDateTime.now() + " => " + "%d-%d的总和 = %d" + "\n", m, n, total);
              }
          }
      
          class SumTask111 implements Callable<Integer> {
              // 定义该线程中的计算和的开始 结束
              private long startNumber, endNumber;
      
              public SumTask111(long startNumber, long endNumber) {
                  this.startNumber = startNumber;
                  this.endNumber = endNumber;
              }
      
              @Override
              public Integer call() throws Exception {
                  int sum = 0;
                  for (long i = startNumber; i <= endNumber; i++) {
                      sum += i;
                  }
                  Thread.sleep(new Random().nextInt(1000));
                  System.out.printf(LocalDateTime.now() + " => SumTask111 call() %s: %d\n", Thread.currentThread().getName(), sum);
                  return sum;
              }
          }
      
  • 总结

    • 掌握共享线程池原理
    • 熟悉 Executor框架, 提高多线程执行效率

猜你喜欢

转载自www.cnblogs.com/sweetXiaoma/p/12725902.html