美文网首页
Java高效并行执行框架介绍

Java高效并行执行框架介绍

作者: 郭彦超 | 来源:发表于2021-05-08 10:45 被阅读0次

    背景

    最近对易企秀推荐系统框架进行了一次升级,将原有详情页的单路召回(基于内容相似性),调整为可支持基于协同、关联规则、画像标签等多路算法召回模式,召回是从海量的数据里快速拿到相对少量的数据,要快而准,为了满足基本的性能指标,这里的召回模块需要考虑支持并行执行。


    某电商架构图参考 易企秀商品推荐框架

    Fork/Join框架是JAVA7提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架


    框架优势

    该框架采用工作窃取算法,比传统的Executor方式更加高效与简单,不需要再单独维护计数器了;工作窃取算法指的是某个线程从其他队列里窃取任务来执行。使用的场景是一个大任务拆分成多个小任务,为了减少线程间的竞争,把这些子任务分别放到不同的队列中,并且每个队列都有单独的线程来执行队列里的任务,线程和队列一一对应。但是会出现这样一种情况:A线程处理完了自己队列的任务,B线程的队列里还有很多任务要处理。A是一个很热情的线程,想过去帮忙,但是如果两个线程访问同一个队列,会产生竞争,所以A想了一个办法,从双端队列的尾部拿任务执行。而B线程永远是从双端队列的头部拿任务执行(任务是一个个独立的小任务),这样感觉A线程像是小偷在窃取B线程的东西一样。

    简单示例

    package ai.djl.examples.inference;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.RecursiveTask;
    
    public class MyTest extends RecursiveTask<List<Integer>> {
        private int cn = 0;
        public MyTest(int a){
            this.cn = a;
        }
        public static void main(String[] args) {
            long time1 = System.currentTimeMillis();
            MyTest t1 = new MyTest(3);    // 任务1耗时600ms
            MyTest t2 = new MyTest(5);   // 任务2耗时1s
            t1.fork();
            t2.fork();
            List<Integer> l1 = t1.join();
            List<Integer> l2 = t2.join();
            l1.addAll(l2);
            System.out.println(l1+": "+(System.currentTimeMillis() - time1)); //如果串行执行,执行时间会大于1600ms
        }
        @Override
        protected List<Integer> compute() {
            try {
                Thread.sleep(cn*200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            List<Integer> ls = new ArrayList<>();
            for(int i=0; i<cn; i++){
                ls.add(i);
            }
            return ls;
        }
    }
    
    
    

    相关文章

      网友评论

          本文标题:Java高效并行执行框架介绍

          本文链接:https://www.haomeiwen.com/subject/dmqudltx.html