zoukankan      html  css  js  c++  java
  • Java并发编程从入门到精通

    1、综述:化繁为简,分而治之;递归的分解和合并,直到任务小到可以接受的程度;
    2、Future任务机制:
      Future接口就是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果;必要时可以通过get方法获取执行结果,该方法会阻塞直到任务会返回结果;也就是说Future接口提供三种功能:判断任务是否完成、能够中断任务、能够获取任务执行结果;
      Future接口里面的常用方法;
    3、FutureTask:
      FutureTask类是Future接口唯一的实现类;
      FutureTask类实现了Runnable接口和Future接口,所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值;
      FutureTask的两个构造器;

     1 /**
     2  * FutureTask的使用
     3  */
     4 package thread06;
     5 
     6 import java.util.concurrent.Callable;
     7 import java.util.concurrent.ExecutionException;
     8 import java.util.concurrent.FutureTask;
     9 
    10 public class FutureTaskTest01
    11 {
    12     public static void main(String[] args) throws InterruptedException, ExecutionException
    13     {
    14         MySon myson = new MySon("Thread Son1");
    15         FutureTask<String> ft1 = new FutureTask<String>(myson);
    16         new Thread(ft1).start();
    17         // 如果调用了get()方法,那么只有得到返回结果后才会继续往下面执行
    18         // 不调用get()方法(不想获取返回结果),直接继续往下走
    19         System.out.println(ft1.get());
    20         
    21         // 执行完指定线程,返回指定结果(22)
    22         FutureTask<Integer> ft2 = new FutureTask<Integer>(new MyRun(), 22);
    23         new Thread(ft2).start();
    24         System.out.println("result_" + ft2.get());
    25         
    26         System.out.println("Thread Main end!");
    27     }
    28 }
    29 
    30 class MySon implements Callable<String>
    31 {
    32     private String name;
    33     
    34     public MySon(String name)
    35     {
    36         this.name = name;
    37     }
    38     
    39     @Override
    40     public String call() throws Exception
    41     {
    42         Thread.sleep(1000L);
    43         System.out.println(name + "任务计算完成");
    44         return "result_11";
    45     }
    46 }
    47 
    48 class MyRun implements Runnable
    49 {
    50     @Override
    51     public void run()
    52     {
    53         try
    54         {
    55             Thread.sleep(1000L);  // 模拟干活
    56         } catch (InterruptedException e)
    57         {
    58             e.printStackTrace();
    59         }
    60         
    61         System.out.println("特定线程2完成任务");
    62     }
    63 }
    64 
    65 /*
    66 任务实现Callable接口,可以返回结果;
    67 任务实现Runnable接口,不可以返回结果,但可以通过FutureTask变相返回指定结果;
    68 */
    FutureTask的使用

    4、Future使用场景:
      实际工作中,可能需要统计各种类型的报表呈现结果,可能一个大的报表需要依赖很多小的模块的运算结果,一个线程做可能又比较慢,就可以拆分成N多个小线程,然后将其结果合并起来作为大的报表呈现结果;接下来的Fork/Join就是基于Future实现的;
    5、什么是Fork/Join框架:
      是一个用于并行执行任务的框架;是一个把大任务分割成若干个小任务执行,最终汇总每个小任务结果后得到大任务结果的框架;
    6、Fork/Join的JDK里面的家族:
    7、Fork/Join框架的实现原理:
    8、异常处理机制和办法:
    9、Fork/Join模式优缺点及其实际应用场景:
      优点:对于符合Fork/Join模式的应用,软件开发人员不再需要处理各种并行相关事务,例如同步、通信等,以难以调试而闻名的死锁和data race等错误也就不会出现,提升了思考问题的层次;并行分发策略,仅仅关注如何划分任务和组合中间结果,将剩下的事情丢给Fork/Join框架完成即可;
      缺点:如果拆分的对象过多时,小心一下子把内存撑满;等待线程的CPU资源释放了,但是线程对象等待时不会被垃圾机制回收;
      使用场景:对于树形结构类型的数据的处理和遍历非常合适;

     1 /**
     2  * Fork/Join框架的使用:计算 1+2+3+4+5 的结果
     3  */
     4 package thread06;
     5 
     6 import java.util.concurrent.ExecutionException;
     7 import java.util.concurrent.ForkJoinPool;
     8 import java.util.concurrent.Future;
     9 import java.util.concurrent.RecursiveTask;
    10 
    11 public class ForkJoinTest01
    12 {
    13     public static void main(String[] args) throws InterruptedException, ExecutionException
    14     {
    15         ForkJoinPool pool = new ForkJoinPool();
    16         
    17         CountTask task1 = new CountTask(1, 5);
    18         Future<Integer> future = pool.submit(task1);
    19         System.out.println("1-5最终相加的结果为:" + future.get());
    20         
    21         CountTask task2 = new CountTask(1, 100);
    22         Future<Integer> future2 = pool.submit(task2);
    23         System.out.println("1-100最终相加的结果为:" + future2.get());
    24     }
    25 }
    26 
    27 class CountTask extends RecursiveTask<Integer>
    28 {
    29     private static final long serialVersionUID = 1L;
    30     
    31     private static int splitSize = 2;
    32     private int start;
    33     private int end;
    34     
    35     public CountTask(int start, int end)
    36     {
    37         this.start = start;
    38         this.end = end;
    39     }
    40     
    41     @Override
    42     protected Integer compute()
    43     {
    44         int sum = 0;
    45         
    46         // 如果任务已经不需要再拆分了,就开始计算
    47         boolean canCompute = (end - start) <= splitSize;
    48         if(canCompute)
    49         {
    50             // 如果是 1+2+3 也是走这个分支
    51             for(int i=start;i<=end;i++)
    52             {
    53                 sum = sum + i;
    54             }
    55         }
    56         else
    57         {
    58             // 拆分成两个子任务
    59             int middle = (start + end) / 2;
    60             CountTask firstTask = new CountTask(start, middle);
    61             CountTask secondTask = new CountTask(middle+1, end);
    62             
    63             // 子任务在调用fork方法时,又会进入compute方法,看看当前子任务是否需要继续分割成孙任务,
    64             // 如果不需要继续分割,则执行当前子任务并返回结果
    65             firstTask.fork();  // 开始计算
    66             secondTask.fork();
    67             
    68             // 获得第一个子任务的结果,得不到结果,此线程不会往下面执行
    69             int firstResult = firstTask.join();
    70             int secondResult = secondTask.join();
    71             
    72             // 合并两个儿子的执行结果
    73             sum = firstResult + secondResult;
    74         }
    75         
    76         return sum;
    77     }
    78     
    79 }
    Fork/Join框架的使用:计算 1+2+3+4+5 的结果
  • 相关阅读:
    java实验报告(实验五)
    java实验报告(实验三)
    java读书笔记二
    总结报告
    Android实践项目汇报(总结)-修改
    Android实践项目汇报(总结)
    Android实践项目汇报(四)
    Android实践项目汇报(三)
    Android实践项目汇报(二)
    Android实践项目汇报-改(一)
  • 原文地址:https://www.cnblogs.com/kehuaihan/p/8460301.html
Copyright © 2011-2022 走看看