通过多线程把大任务变成多个小任务并发处理的进一步总结

前面已经对通过线程池把大任务分成小任务并汇总小任务结果的逻辑进行了简单总结,现在对该场景进行进一步总结

一:使用ThreadPoolExecutor方法

1.把大任务分成多个可以让线程执行的小任务,并创建一个list容器,存储这些小任务

2.以该list为入参,调用线程池的invokeAll()方法,并发执行这些小任务。该方法的返回值是存储了Future的list

3.遍历返回结果,拿到每一个Future,通过future.get()方法就可以获得对应的线程结果,从而可以拿到所有线程的执行结果

***大任务分成多个小任务的方法

(1)直接创建一个list,调用list.add()并以Callable匿名内部类为入参,每一个Callable匿名内部类都是一个小任务,该小任务的实现逻辑在call()方法中实现。最后得到一个存储了多个Callable任务的list容器。该方法的缺点是不能从父线程中传递参数的子线程中。实际该思路更像是直接创建多个小任务,而不是把大任务进行切割。

(2)创建Callable的实现类,父线程则可以通过构造函数以入参的形式传递参数到Callable实现类,进而传递给对应的子线程。然后把该实现类加入到list容器中,即完成了大任务的分割。比如1一个list存储着1-100的数字,现在需要分成5组,每一个线程负责一组任务,则可以通过把list切割,把对应子数组以参数的形式传递给Callable实现类即可(当然也可以传递原数组,起始点,结束点等参数来确定每一个线程的任务)

二:通过ThreadPoolExecutor来并发执行任务,由于每一个线程自己的任务执行时长可能不一样,当把自己的任务完成后,线程就会处于空闲状态(假设没有新任务),那么就浪费了线程资源。通过ForkJoinPool代替ExecutorThreadPool,则可以充分利用线程资源。ForkJoinPool中的线程都有一个属于自己的工作任务队列,该池会通过工作任务窃取的算法,让空闲线层会从繁忙线程的任务队列中窃取到工作任务并执行

        1.继承特定父类(RecursiveAction/RecursiveTask)

        2.重写Compute方法,并在该方法完成任务分组与执行。(通过fork()方法把任务加入到工作线程的任务队列中,通过join()返回当前任务的执行结果)

        3.以该子类为入参,调用ForkJoinPool的submit()方法执行任务

三:ForkJoinPool简单概括

1.fork():如果线程数没有达到阈值,则会创建一个新的工作线程(父线程为当前线程),并把任务放入该新的工作线程的任务队列中;如果线程数已经达到阈值,则把任务加入到当前线程的任务队列中。而当前任务就是当前对象的compute()方法里面的逻辑。

2.工作任务分为外部任务与内部任务,外部任务是指在非ForkJoinThread运行的任务,如main线程中通过ForkJoinPool.submit()提交的任务,该类任务会被放到线程池的工作队列中,由该线程池创建一个ForkJoinThread去执行。内部任务是指在ForkJoinThread运行的任务,如task.fork(),该任务会放入工作线程的任务队列中(工作线程可能是当前ForkJoinThread线程,也可能是新创建的ForkJoinThread)

3.继承关系:
    (1)ForkJoinPool与ExecutorThreadPool都是共同继承AbstractExecutorService,两者功能类似
    (2)ForkJoinThread继承自Thread类,提供了工作队列等扩展
    (3)FutureJoinTask实现了Future接口,同样可以获得异步返回值

最后:附上后端技术交流圈,欢迎各位大佬入圈交流技术......V:ff1341658(先添加好友后拉群,添加好友时请备注:小白不黑)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值