任务_任务计划 - CSDN
精华内容
参与话题
  • 任务学习

    万次阅读 2018-01-12 16:47:04
    任务学习(Multitask learning)是迁移学习算法的一种,迁移学习可理解为定义一个一个源领域source domain和一个目标领域(target domain),在source domain学习,并把学习到的知识迁移到target domain,提升...

    简介:
    多任务学习(Multitask learning)是迁移学习算法的一种,迁移学习可理解为定义一个一个源领域source domain和一个目标领域(target domain),在source domain学习,并把学习到的知识迁移到target domain,提升target domain的学习效果(performance)。


    概念解析

    多任务学习(Multi-task learning):由于我们的关注点集中在单个任务上,我们忽略了可能帮助优化度量指标的其它信息。具体来说,这些信息来自相关任务的训练信号。通过共享相关任务之间的表征,可以使我们的模型更好地概括原始任务。这种方法被称为多任务学习(MTL)。其也是一种归纳迁移机制,主要目标是利用隐含在多个相关任务的训练信号中的特定领域信息来提高泛化能力,多任务学习通过使用共享表示并行训练多个任务来完成这一目标。归纳迁移是一种专注于将解决一个问题的知识应用到相关的问题的方法,从而提高学习的效率。比如,学习行走时掌握的能力可以帮助学会跑,学习识别椅子的知识可以用到识别桌子的学习,我们可以在相关的学习任务之间迁移通用的知识。此外,由于使用共享表示,多个任务同时进行预测时,减少了数据来源的数量以及整体模型参数的规模,使预测更加高效。因此,在多个应用领域中,可以利用多任务学习来提高效果或性能,比如垃圾邮件过滤、网页检索、自然语言处理、图像识别、语音识别等。
    归纳偏执(inductive bias):归纳迁移的目标是利用额外的信息来源来提高当前任务的学习性能,包括提高泛化准确率、学习速度和学习的模型的可理解性。提供更强的归纳偏执是迁移提高泛化能力的一种方法,可以在固定的训练集上产生更好的泛化能力,或者减少达到同等性能水平所需要的训练样本数量。归纳偏执会导致一个归纳学习器更偏好一些假设,多任务学习正是利用隐含在相关任务训练信号中的信息作为一个归纳偏执来提高泛化能力。归纳偏置的作用就是用于指导学习算法如何在模型空间中进行搜索,搜索所得模型的性能优劣将直接受到归纳偏置的影响,而任何一个缺乏归纳偏置的学习系统都不可能进行有效的学习。不同的学习算法(如决策树,神经网络,支持向量机等)具有不同的归纳偏置,人们在解决实际问题时需要人工地确定采用何种学习算法,实际上也就是主观地选择了不同的归纳偏置策略。一个很直观的想法就是,是否可以将归纳偏置的确定过程也通过学习过程来自动地完成,也就是采用“学习如何去学(learning to learn)”的思想。多任务学习恰恰为上述思想的实现提供了一条可行途径,即利用相关任务中所包含的有用信息,为所关注任务的学习提供更强的归纳偏置。


    详解

    1.从机器学习的角度来看,我们将多任务学习视为一种归约迁移(inductive transfer)。归约迁移(inductive transfer)通过引入归约偏置(inductive bias)来改进模型,使得模型更倾向于某些假设。举例来说,常见的一种归约偏置(Inductive bias)是L1正则化,它使得模型更偏向于那些稀疏的解。在多任务学习场景中,归约偏置(Inductive bias)是由辅助任务来提供的,这会导致模型更倾向于那些可以同时解释多个任务的解,这样做会使得模型的泛化性能更好。

    2.深度学习中两种多任务学习模式:隐层参数的硬共享与软共享
    (1)参数的硬共享机制:参数的硬共享机制是神经网络的多任务学习中最常见的一种方式,一般来讲,在实际应用中,通常通过在所有任务之间共享隐藏层,同时保留几个特定任务的输出层来实现。硬共享机制降低了过拟合的风险。事实上,有文献证明了这些共享参数过拟合风险的阶数是N,其中N为任务的数量,比任务相关参数的过拟合风险要小。直观来将,这一点是非常有意义的。越多任务同时学习,我们的模型就能捕捉到越多任务的同一个表示,从而导致在我们原始任务上的过拟合风险越小。
    (2)参数的软共享机制(基于约束的共享(regularization based)):每个任务都由自己的模型,自己的参数。在共享 Soft 参数时,每个任务都有自己的参数和模型。模型参数之间的距离是正则化的,以便鼓励参数相似化。我们对模型参数的距离进行正则化来保障参数的相似。如有文献使用L2距离正则化,而也有文献使用迹正则化(trace norm)。用于深度神经网络中的软共享机制的约束很大程度上是受传统多任务学习中正则化技术的影响。约束深度神经网络 Soft 参数共享的思想受到了 MTL 正则化技术的极大启发,这种思想已经用于其它模型开发。

    3.多任务学习的有效性
    由于所有任务都或多或少存在一些噪音,例如,当我们训练任务A上的模型时,我们的目标在于得到任务A的一个好的表示,而忽略了数据相关的噪音以及泛化性能。由于不同的任务有不同的噪音模式,同时学习到两个任务可以得到一个更为泛化的表示(As different tasks have different noise patterns, a model that learns two tasks simultaneously is able to learn a more general representations.)。如果只学习任务A要承担对任务A过拟合的风险,然而同时学习任务A与任务B对噪音模式进行平均,可以使得模型获得更好表示F;
    若任务噪音严重,数据量小,数据维度高,则对于模型来说区分相关与不相关特征变得困难。多任务有助于将模型注意力集中在确实有影响的那些特征上,是因为其他任务可以为特征的相关与不相关性提供额外的证据;
    对于任务B来说很容易学习到某些特征G,而这些特征对于任务A来说很难学到。这可能是因为任务A与特征G的交互方式更复杂,或者因为其他特征阻碍了特征G的学习。通过多任务学习,我们可以允许模型窃听(eavesdrop),即使用任务B来学习特征G;
    多任务学习更倾向于学习到一类模型,这类模型更强调与其他任务也强调的那部分表示。由于一个对足够多的训练任务都表现很好的假设空间,对来自于同一环境的新任务也会表现很好,所以这样有助于模型展示出对新任务的泛化能力;
    单任务学习时,梯度的反向传播倾向于陷入局部极小值。多任务学习中不同任务的局部极小值处于不同的位置,通过相互作用,可以帮助隐含层逃离局部极小值;
    添加的任务可以改变权值更新的动态特性,可能使网络更适合多任务学习。比如,多任务并行学习,提升了浅层共享层(shared representation)的学习速率,可能,较大的学习速率提升了学习效果;
    正则化机制:多任务学习通过引入归纳偏置(inductive bias)起到与正则化相同的作用。正是如此,它减小了模型过拟合的风险,同时降低了模型的Rademacher复杂度,即拟合随机噪音的能力。

    4.多任务学习MTL 有很多形式:联合学习(joint learning)、自主学习(learning to learn)和带有辅助任务的学习(learning with auxiliary task)等都可以指 MTL。一般来说,优化多个损失函数就等同于进行多任务学习(与单任务学习相反)。这些情况有助于你明确地思考如何在 MTL 方面做尝试并从中获得启发。

    5.多任务学习与其他学习算法之间的关系
    迁移学习:自1995年以来,迁移学习吸引了众多的研究者的目光,迁移学习有很多其他名字:学习去学习(Learning to learn)、终身学习(life-long learning)、推导迁移(inductive transfer)、知识强化(knowledge consolidation)、上下文敏感性学习(context-sensitive learning)、基于知识的推导偏差(knowledge-based inductive bias)、累计/增量学习(increment / cumulative learning)等。在机器学习、深度学习和数据挖掘的大多数任务中,会假设training和inference时,采用的数据服从相同的分布(distribution)、来源于相同的特征空间(feature space)。但在现实应用中,这个假设很难成立,往往遇到一些问题:

    a.带标记的训练样本数量有限。比如,处理A领域(target domain)的分类问题时,缺少足够的训练样本。同时,与A领域相关的B(source domain)领域,拥有大量的训练样本,但B领域与A领域处于不同的特征空间或样本服从不同的分布。
    b.数据分布会发生变化。数据分布与时间、地点或其他动态因素相关,随着动态因素的变化,数据分布会发生变化,以前收集的数据已经过时,需要重新收集数据,重建模型。

    多任务学习是针对数据给出多个监督信息(标签)进行学习,例如识别一张图像中的脸是否是人脸、脸部表情、性别、年龄等,识别图像中车的颜色、车型、姿态等,都属于多任务分类。
    多标签学习(Multilabel learning)是多任务学习中的一种,建模多个label之间的相关性,同时对多个label进行建模,多个类别之间共享相同的数据/特征。
    多类别学习(Multiclass learning)是多标签学习任务中的一种,对多个相互独立的类别(classes)进行建模。这几个学习之间的关系如下图所示:
    这里写图片描述


    6.实例介绍

    (1)人脸识别:多任务学习给出多个监督信息(标签),利用任务之间的相关性互相促进。香港中文大学汤晓鸥组发表在NIPS14的论文《Deep Learning Face Representation by Joint Identification-Verification》,提出了一种联合训练人脸确认损失和人脸分类损失的多任务人脸识别网络DeepID2(Deep IDentification-verification features)。DeepID2中共有两个损失函数,分别为人脸分类损失函数和人脸验证loss。结合两个损失学习效果会更好,原因是:分类任务旨在区分不同类,理论上,只要类别不同学习到的特征肯定不同,重点在于扩大类间距离,而验证这个任务从另一个方面提取特征:缩小类内距离扩大类间相对距离!但是后者提取到的特征不能用于分类,只能做二值区分。所以说两个任务具有一定的互补性!
    这里写图片描述

    (2)脸部特征点检测:脸部特征点检测受遮挡和姿势变化等问题的影响,:通过多任务学习具有提高检测健壮性的可能性,而不是把检测任务视为单一和独立的问题。多任务学习希望把优化脸部特征点检测和一些不同但细微相关的任务结合起来,比如头部姿势估计和脸部属性推断。脸部特征点检测不是一个独立的问题,它的预测会被一些不同但细微相关的因素影响。比如一个正在笑的孩子会张开嘴,有效地发现和利用这个相关的脸部属性将帮助更准确地检测嘴角。
    如下图,一个TCDCN模型,除了检测特征点任务,还有识别眼镜、笑脸、性别和姿态这四个辅助任务,通过与其它网络的对比,可以看出辅助任务使主任务的检测更准确。
    这里写图片描述

    TCDCN通过随机梯度下降进行学习,不同的任务有不同的损失函数和学习难度,因此有不同的收敛速度,网络结构如下图所示。早期的方法通过探索任务之间的关系,比如学习所有任务权重的协方差矩阵来解决收敛速度不同的问题,但是这种方法只能在所有任务的损失函数相同时才能应用。TCDCN采用一种尽快停止辅助任务的方法避免这些任务对训练集过拟合后影响主任务的学习:即在训练开始时,TCDCD受所有任务的约束,避免陷入不好的局部最优;随着训练的进行,有些辅助任务将不再使主任务受益,它们的学习过程将被停止。
    这里写图片描述

    (3)目标检测: Fast R-CNN。Fast R-CNN 是一个物体检测的快速的基于区域的卷积网络,其中也有多任务深度学习的应用,图中展示了Fast R-CNN的网络结构。一张图片和多个RoI(感兴趣区域)输入到一个全卷积网络,每个RoI会进入一个固定大小的feature map,然后被全连接层映射到一个特征向量。每个RoI有两个输出:softmax概率和每个分类的矩形框回归补偿。

    这里写图片描述
    一个Fast R-CNN网络有两个输出层:第一个输出K+1个分类的概率分布;第二个输出每个分类的边框回归补偿。每个训练RoI标注为一个参考标准分类u和一个参考标准边框回归对象v,在每个标注的RoI用多任务损失函数L来共同训练分类和矩形框回归。


    总结
    现实世界中很多问题不能分解为一个一个独立的子问题,即使可以分解,各个子问题之间也是相互关联的,通过一些共享因素或共享表示(share representation)联系在一起。把现实问题当做一个个独立的单任务处理,忽略了问题之间所富含的丰富的关联信息。多任务学习就是为了解决这个问题而诞生的。把多个相关(related)的任务(task)放在一起学习。这样做真的有效吗?答案是肯定的。多个任务之间共享一些因素,它们可以在学习过程中,共享它们所学到的信息,这是单任务学习所具备的。相关联的多任务学习比单任务学习能去的更好的泛化(generalization)效果。

    多任务学习是一种归纳迁移机制,利用额外的信息来源来提高当前任务的学习性能,包括提高泛化准确率、学习速度和已学习模型的可理解性。在学习一个问题的同时,可以通过使用共享表示来获得其他相关问题的知识。

    能提高泛化能力的可能原因有三:第一,不相关任务对于聚合梯度的贡献相对于其他任务来说可以视为噪声,不相关任务也可以通过作为噪声源来提高泛化能力;第二,增加任务会影响网络参数的更新,比如增加了隐层有效的学习率;第三,多任务网络在所有任务之间共享网络底部的隐层,或许更小的容量就可以获得同水平或更好的泛化能力。因此,我们需要关注如何选择多个相关任务及数据集使网络更好地泛化,有四种机制可以帮助多任务学习网络更好地泛化:统计数据增强、属性选择、信息窃取、表示偏置。

    多任务学习将会在越来越多的领域作为一种提高神经网络学习能力的手段被广泛应用。 深度学习网络是具有多个隐层的神经网络,在深度学习网络中应用多任务学习是一种很自然的想法。机器视觉领域有广泛的多任务学习应用,主要方式包括:
    多个任务并行输出;
    同时做分类和回归或使用不同的损失函数
    多个任务如流水线般,辅助任务附加在主任务后面。


    Reference
    机器之心:https://www.jiqizhixin.com/articles/2017-06-23-5
    [1] T. Evgeniouand M. Pontil. Regularized multi-task learning. In Proceeding of thetenth ACM SIGKDD international conference on Knowledge Discovery and DataMining, 2004.

    [2] T. Jebara. MultitaskSparsity via Maximum Entropy Discrimination. In Journal of Machine LearningResearch, (12):75-110, 2011.

    [3] A. Argyriou,T. Evgeniou and M. Pontil. Convex multitask feature learning. In MachineLearning, 73(3):243-272, 2008.

    [4] T. G. Dietterich, L. Pratt, and S. Thrun, Eds., “Machine Learning – Special issue on inductive transfer,” Mach Learn, vol. 28, no. 1, 1997.

    [5] L. Holmstrom and P. Koistinen, “Using additive noise in back-propagation training,” IEEE Trans. Neural Netw., vol. 3, no. 1, pp. 24–38, Jan. 1992.

    [6] Z. Zhang, P. Luo, C. C. Loy, and X. Tang, “Facial Landmark Detection by Deep Multi-task Learning,” in Computer Vision – ECCV 2014: 13th European Conference, Zurich, Switzerland, September 6-12, 2014, Proceedings, Part VI, D. Fleet, T. Pajdla, B. Schiele, and T. Tuytelaars, Eds. Cham: Springer International Publishing, 2014, pp. 94–108.

    [7] Y. Sun, Y. Chen, X. Wang, and X. Tang, “Deep Learning Face Representation by Joint Identification-Verification,” in Advances in Neural Information Processing Systems 27, Z. Ghahramani, M. Welling, C. Cortes, N. D. Lawrence, and K. Q. Weinberger, Eds. Curran Associates, Inc., 2014, pp. 1988–1996.

    [8] G. B. Huang, M. Ramesh, T. Berg, and E. Learned-Miller, “Labeled faces in the wild: A database for studying face recognition in unconstrained environments,” Technical Report 07-49, University of Massachusetts, Amherst, 2007.

    [9] R. Girshick, “Fast R-CNN,” in The IEEE International Conference on Computer Vision (ICCV), 2015.

    展开全文
  • JavaScript 宏任务和微任务

    千次阅读 2019-10-11 11:49:28
    JavaScript 宏观任务和微观任务 概念 宏观任务:宿主发起的任务为宏观任务,如setTimeout、setInterval、setImmediate,I/O 微观任务:JavaScript引擎发起的任务为微观任务,如Promise JavaScript引擎等待宿主环境...

    JavaScript 宏观任务和微观任务

    概念

    在这里插入图片描述
    宏观任务:宿主发起的任务为宏观任务,如setTimeout、setInterval、setImmediate,I/O
    微观任务:JavaScript引擎发起的任务为微观任务,如Promise

    JavaScript引擎等待宿主环境分配宏观任务,宏观任务的队列可以理解为一个事件循环:

    while(TRUE) {
      r = wait();
      execute(r);
    }
    

    每个宏观任务中又包含一个微观任务队列
    有:

    • setTimeout等宿主API,会添加宏观任务
    • Promise永远在队列尾部添加微观任务

    分析异步执行的方法

    1. 分析有多少个宏观任务
    2. 在每个宏观任务中,分析有多少个微观任务
    3. 根据调用次序,确定宏观任务中微观任务执行次序
    4. 根据宏观任务调用次序和触发原则,确定宏观任务执行次序
    5. 确定整个次序

    promise

     var r = new Promise(function(resolve, reject) {
          console.log("a");
          resolve();
        });
        setTimeout(() => console.log("d"), 0);
        r.then(() => console.log("c"));
        console.log("b");
    
        // 执行顺序 a b c d
    
    
    
        setTimeout(() => console.log("d"), 0);
        var r1 = new Promise(function(resolve, reject) {
          resolve();
        });
        r1.then(() => {
          var begin = Date.now();
          while (Date.now() - begin < 1000);
          console.log("c1");
          new Promise(function(resolve, reject) {
            resolve();
          }).then(() => console.log("c2"));
        });
        // 虽然第二个promise 间隔了1秒 但是还是 先于setTimeout执行
        // c1  c2  d
       
    
    function sleep(duration) {
          return new Promise(function(resolve, reject) {
            console.log("b");
            setTimeout(resolve, duration);
          });
        }
        console.log("a");
        sleep(5000).then(() => console.log("c"));
    
        // 将setTimeout封装成可以用于异步的函数
     	//a b c
    
    

    async/await

    是ES7新特性,提供了用for if来编写异步代码的方式
    async函数必定返回Promise,所有返回Promise的函数都可以认为是异步函数

    • async用来表示函数是异步的,定义的函数会返回一个promise对象,可以使用then方法添加回调函数。我们把所有返回 Promise 的函数都可以认为是异步函数。[所以它也是微观任务]

    • await 后面可以跟任何的JS 表达式。虽然说 await 可以等很多类型的东西,但是它最主要的意图是用来等待 Promise 对象的状态被 resolved。如果await的是 promise对象会造成异步函数停止执行并且等待 promise 的解决,如果等的是正常的表达式则立即执行。

    async可以嵌套

    function sleep(duration) {
      return new Promise(function(resolve, reject) {
        setTimeout(resolve, duration)
      })
    }
    async function foo(name) {
      await sleep(2000)
      console.log(name)
    }
    async function foo2() {
      await foo("a")
      await foo("b")
    }
    foo2()
    //a b
    
       var obj = document.getElementById("animate");
        function timeSleep(times) {
          return new Promise((resolve, reject) => {
            setTimeout(resolve, times);
          });
        }
       async function colorChange(color, times) {
          obj.style.backgroundColor = color;
          await timeSleep(times);
        }
    
        async function trafciLigth() {
          // while (true) {
          await colorChange("green", 3000);
          await colorChange("red", 2000);
          await colorChange("yellow", 1000);
          // }
        }
        trafciLigth();
    	//绿 红 黄
    
    展开全文
  • 任务、微任务

    千次阅读 2018-11-19 10:27:51
    任务与微任务? B-树中含511个关键字,B-树为3阶,则包含叶子节点层该树最大深度为? 8 9 10 11

    宏任务与微任务

    这是前端笔试题常考的一个点,给你一段代码,写出代码的输出结果。以前总觉得了解异步与同步的区别,知道异步任务放入另一个队列就可以了,实际上没有这么简单。看了许多博客,总结了一下,总算是明白了。

    什么是宏任务、微任务

    先来了通俗易懂的例子:
    去银行办理业务的人就是一个个宏任务,当宏任务P1在柜台办理业务时,其它任务都需等待,当一个宏任务P1办理业务结束时,柜台职员会询问他还有没有其它微任务,如果他还有其他业务,则其他宏任务都需等待。就是微任务是在宏任务之前执行。

    宏任务、微任务有哪些

    宏任务包括:script(整体代码), setTimeout, setInterval, setImmediate, I/O, UI rendering。

    微任务包括: Promises, Object.observe, MutationObserver

    宏任务、微任务的执行顺序

    执行顺序:先执行同步代码,遇到异步宏任务则将异步宏任务放入宏任务队列中,遇到异步微任务则将异步微任务放入微任务队列中,当所有同步代码执行完毕后,再将异步微任务从队列中调入主线程执行,微任务执行完毕后再将异步宏任务从队列中调入主线程执行,一直循环直至所有任务执行完毕。

    实例剖析

    • 例1
    setTimeout(function(){
    	console.log('1');
    });
    new Promise(function(resolve){		    
    	console.log('2');
    	resolve();
    }).then(function(){		    
    	console.log('3');
    }); 		
    console.log('4');
    
    1. 遇到setTimout,异步宏任务,放入宏任务队列中;
    2. 遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出2
    3. 而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
    4. 遇到同步任务console.log(‘4’);输出4;主线程中同步任务执行完
    5. 从微任务队列中取出任务到主线程中,输出3,微任务队列为空
    6. 从宏任务队列中取出任务到主线程中,输出1,宏任务队列为空,结束~

    控制台测试一下,输出2 4 3 1;符合预期

    1. 例2
    setTimeout(()=>{
      new Promise(resolve =>{
      	resolve();
      }).then(()=>{
      	console.log('test');
      });
    
      console.log(4);
    });
    
    new Promise(resolve => {
      resolve();
      console.log(1)
    }).then( () => {
      console.log(3);
      Promise.resolve().then(() => {
        console.log('before timeout');
      }).then(() => {
        Promise.resolve().then(() => {
          console.log('also before timeout')
        })
      })
    })
    console.log(2);
    
    1. 遇到setTimeout,异步宏任务,将() => {console.log(4)}放入宏任务队列中;
    2. 遇到new Promise,new Promise在实例化的过程中所执行的代码都是同步进行的,所以输出1
    3. 而Promise.then中注册的回调才是异步执行的,将其放入微任务队列中
    4. 遇到同步任务console.log(2),输出2;主线程中同步任务执行完
    5. 从微任务队列中取出任务到主线程中,输出3,此微任务中又有微任务,Promise.resolve().then(微任务a).then(微任务b),将其依次放入微任务队列中;
    6. 从微任务队列中取出任务a到主线程中,输出 before timeout
    7. 从微任务队列中取出任务b到主线程中,任务b又注册了一个微任务c,放入微任务队列中;
    8. 从微任务队列中取出任务c到主线程中,输出 also before timeout;微任务队列为空
    9. 从宏任务队列中取出任务到主线程,此任务中注册了一个微任务d,将其放入微任务队列中,接下来遇到输出4,宏任务队列为空
    10. 从微任务队列中取出任务d到主线程 ,输出test,微任务队列为空,结束~

    控制台测试输出:1 2 3 before timeout also before timeout 4 test

    展开全文
  • activiti 多实例任务

    万次阅读 多人点赞 2020-01-06 17:16:53
    我们在使用activiti 工作流引擎的时候,最常用的肯定是任务节点,因为在OA系统、审批系统、办公自动化系统中核心的处理就是流程的运转,在流程运转的时候,可能我们有这样的一个需求,在一个任务节点的时候,我们...

    1.1.1. 前言

     

    分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519)

    我们在使用activiti 工作流引擎的时候,最常用的肯定是任务节点,因为在OA系统、审批系统、办公自动化系统中核心的处理就是流程的运转,在流程运转的时候,可能我们有这样的一个需求,在一个任务节点的时候,我们需要多个人对这个节点进行审批,比如实际中这样一个例子,假如是一个部门的投票,这个部门有5个人,那么当5个人都投票的时候大概分为如下几种:

    1.部门所有人都去投票,当所有人都投票完成的时候,这个节点结束,流程运转到下一个节点。(所有的人都需要投票)

    2.部门所有人都去投票,只要有任意2/3的人同意,这个节点结束,流程运转到下一个节点。(部分人投票只要满足条件就算完成)。

    3.部门中有一个部门经理,只要部门经理投票过了,这个节点结束,流程运转到下一个节点(一票否决权)。

    4.部门中根据职位不同,不同的人都不同的权重,当满足条件的时候,这个节点结束,流程运转到下一个节点。比如说所有的人员权重加起来是1,a有0.2的权重,其他的四个人分别是0.1的权重,我们可以配置权重达到0.3就可以走向下一个节点,换言之a的权重是其他人的2倍,那就是a的投票相当于2个人投票。这种需求还是很常见的。

    5.部门所有人都去投票,a投票结束到b,b开始投票结束到c,一直如此,串行执行。最终到最后一个人再统计结果,决定流程的运转。

    上面的五种情况,我们可以提取出来一些信息,我们的activiti 工作流引擎,必须支持如下功能,才能满足上面的需求:

    1.任务节点可以配置自定义满足条件。

    2.任务节点必须支持串行、并行。

    3.任务节点必须支持可以指定候选人或者候选组。

    4.任务节点必须支持可以循环的次数。

    5.任务节点必须支持可以自定义权重。

    6.任务节点必须支持加签、减签。(就是动态的修改任务节点的处理人)

    因为实际上的需求可能比上面的几种情况更加的复杂,上面的6个满足条件,工作流支持前4个,后面的2个条件是不支持的,所以我们必须要扩展activiti 工作流引擎才能使用5、6等的功能。下面我们将详细的介绍前四种条件的使用,在掌握基本使用之后,我们在后面的章节中将详细的介绍,5、6这两种功能以及可能更加复杂的操作。

     

    1.1.2. 串行、并行配置

    为了演示如何使用,我们采用由浅入深的使用,结合流程图、流程定义xml、以及代码和数据库的变化来阐释每一个配置的使用以及含义。

    流程的详细定义如下图所示:

     

    流程的详细定义xml如下所示:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="daling">
      <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">
        <startEvent id="startevent1" name="Start"></startEvent>
        <userTask id="usertask1" name="多实例任务" activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4">
          <multiInstanceLoopCharacteristics isSequential="true">
            <loopCardinality>2</loopCardinality>
          </multiInstanceLoopCharacteristics>
        </userTask>
        <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
        <endEvent id="endevent1" name="End"></endEvent>
        <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_daling">
        <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">
          <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
            <omgdc:Bounds height="55.0" width="105.0" x="370.0" y="90.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="650.0" y="130.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
            <omgdi:waypoint x="215.0" y="167.0"></omgdi:waypoint>
            <omgdi:waypoint x="422.0" y="145.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
            <omgdi:waypoint x="475.0" y="117.0"></omgdi:waypoint>
            <omgdi:waypoint x="667.0" y="130.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>

     

     

     

     

     

    xml配置文件的部分含义如下:

    1.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。

    2.<loopCardinality>2</loopCardinality> 循环2次结束。

    3.<multiInstanceLoopCharacteristics isSequential="true"> 串行并行的配置。

    1.1.2.1. 串行的配置

    修改<multiInstanceLoopCharacteristics isSequential="true"> 中的isSequential为true是串行,isSequential为false是并行。我们测试串行。下面的代码展示启动流程因为是以一个节点所以部署启动后,直接进入多实例任务。

    1.1.2.1.1. 流程的部署

     

    Deployment deploy = repositoryService2.createDeployment()
    .category(category).addClasspathResource("demo1.bpmn").deploy();

     

    1.1.2.1.2. 流程的启动

    /**

     *

     * @param runtimeService

     * @param key

     *            act_re_procdef表的Id

     * @param businessKey

     *            业务单号

     * @return

     */

    public ProcessInstance startProcessInstanceByKey(

    RuntimeService runtimeService, String key, String businessKey) {

    ProcessInstance processInstance = runtimeService

    .startProcessInstanceByKey(key, businessKey);

    return processInstance;

    }

    我们按照上面的步骤启动一个流程看一下数据库的变化。

    ACT_RU_TASK表的数据有了如下图所示:

     

    ACT_RU_IDENTITYLINK表的数据有了如下图所示:

     

    ACT_RU_IDENTITYLINK权限表中,确实把我们设置的人员信息设置进去了,shareniu1,shareniu2,shareniu3,shareniu4现在就有代办信息了。

    ACT_RU_VARIABLE表的数据有了如下图所示:

     

    上面重要的变量需要解释一下,要不然还真不好理解,多任务是怎么运转的。

    1.nrOfInstances  实例总数。

    2.nrOfCompletedInstances  当前还没有完成的实例 nr是number单词缩写 。

    3.loopCounter 已经循环的次数。

    4.nrOfActiveInstances 已经完成的实例个数。

     

    下面我们结束一个任务看一下,流程走到那个节点了。

    1.1.2.1.3. 完成任务

    String taskId="45009";

    demo.getTaskService().complete(taskId);

    接下来看一下数据库表的变化。

    ACT_RU_VARIABLE表的数据有了如下图所示:

     

     

    上面我们仔细的发现,可以看到

    nrOfCompletedInstances、loopCounter、nrOfActiveInstances都加1了,确实多任务就是参考这几个值的变化进行判断的。

    因为我们设置了循环2次,所以我们看看ACT_RU_IDENTITYLINK还有一个任务,因为我们是并行处理的。

    所以我们在结束新的任务看一下流程是不是真的结束了,如果结束了,那么我们循环次数的配置就是正确的。

    1.1.2.1.4. 完成任务

    String taskId="47502";

    demo.getTaskService().complete(taskId);

    下面看一下ACT_RU_TASK,里面没有任务信息了,所以侧面证明循环次数的配置就是正确的。

    接下来我们测试并行任务。除了isSequential="false",其他的配置是一样的。

    1.1.2.2. 并行的配置测试

    除了isSequential="false",其他的配置跟上面的串行是一样一样的。

    重新部署测试,部署后我们启动一个新的流程测试。

    ACT_RU_TASK表如下:

     

    一次性的有2个任务需要处理,因为我们循环的是2次,所以直接就是2个。

    ok串行、并行就讲解到这里。

     

    1.1.3. 串行、并行总结

    我们配置的是循环2次,看以看到不管是并行还是串行,两个代办任务结束之后,流程直接跳转到下一个状态,但是

    我们并没有配置结束条件,所以上面的例子,也可以看出来,如果不配置默认的通过条件,则默认条件是1,后面的源码章节会给大家说明这一点的。

     

    1.1.4. 通过条件的配置

    在上面的串行、并行实例中,我们没有设置通过条件,但是程序按照配置的循环的次数,然后跳转到了下一个状态,可以侧面印证,如果不配置通过条件则默认值就是1.

     

    下面的代码详细的介绍通过条件的配置,具体的配置代码如下:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="daling">
      <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">
        <startEvent id="startevent1" name="Start"></startEvent>
        <userTask id="usertask1" name="多实例任务" activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4">
          <multiInstanceLoopCharacteristics isSequential="false">
            <loopCardinality>4</loopCardinality>
            <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>
          </multiInstanceLoopCharacteristics>
        </userTask>
        <sequenceFlow id="flow1" sourceRef="startevent1" targetRef="usertask1"></sequenceFlow>
        <endEvent id="endevent1" name="End"></endEvent>
        <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_daling">
        <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">
          <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
            <omgdc:Bounds height="55.0" width="105.0" x="371.0" y="140.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="150.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNEdge bpmnElement="flow1" id="BPMNEdge_flow1">
            <omgdi:waypoint x="215.0" y="167.0"></omgdi:waypoint>
            <omgdi:waypoint x="371.0" y="167.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
            <omgdi:waypoint x="476.0" y="167.0"></omgdi:waypoint>
            <omgdi:waypoint x="660.0" y="167.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>

     

     

     

     

     

    1.1.4.1. 配置描述

    <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

    nrOfCompletedInstances、nrOfInstances 变量描述上面已经描述了,我们这里设置的条件是大于1/4的人完成任务,任务就结束了。下面我们代码部署流程,启动流程后进行测试:

    ACT_RU_TASK表如下:

     

    我们随便结束一个任务,看一下ACT_RU_TASK表变化。

    String taskId="60038";

    demo.getTaskService().complete(taskId);

    执行上面的代码,我们很神奇的发现,ACT_RU_TASK表中的其他任务没有了,因为我们配置了4个人,通过条件是1/4,所以任意一个人结束了,流程就结束了。这里我们测试的是并行,串行也是一样的,读者可以自行测试验证。

    1.1.5. 动态的配置

    上面的几种方式,我们定义xml的时候,循环的次数是固定写在xml中的,也就是说我们配置的是循环2次,那么所有的流程实例都是循环2次,这样就不灵活了,程序当然是灵活了比较好,所以在实际开发中,我们可以使用下面的这种方式操作,使程序更加的灵活。

    程序的xml配置如下所示:

     

    <?xml version="1.0" encoding="UTF-8"?>
    <definitions xmlns="http://www.omg.org/spec/BPMN/20100524/MODEL" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:activiti="http://activiti.org/bpmn" xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI" xmlns:omgdc="http://www.omg.org/spec/DD/20100524/DC" xmlns:omgdi="http://www.omg.org/spec/DD/20100524/DI" typeLanguage="http://www.w3.org/2001/XMLSchema" expressionLanguage="http://www.w3.org/1999/XPath" targetNamespace="daling">
      <process id="daling" name="name_daling" isExecutable="true" activiti:candidateStarterUsers="a,b,c,d">
        <startEvent id="startevent1" name="Start"></startEvent>
        <userTask id="usertask1" name="多实例任务" activiti:assignee="${assignee}">
          <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">
            <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>
          </multiInstanceLoopCharacteristics>
        </userTask>
        <endEvent id="endevent1" name="End"></endEvent>
        <sequenceFlow id="flow2" sourceRef="usertask1" targetRef="endevent1"></sequenceFlow>
        <userTask id="usertask2" name="User Task"></userTask>
        <sequenceFlow id="flow3" sourceRef="startevent1" targetRef="usertask2"></sequenceFlow>
        <sequenceFlow id="flow4" sourceRef="usertask2" targetRef="usertask1"></sequenceFlow>
      </process>
      <bpmndi:BPMNDiagram id="BPMNDiagram_daling">
        <bpmndi:BPMNPlane bpmnElement="daling" id="BPMNPlane_daling">
          <bpmndi:BPMNShape bpmnElement="startevent1" id="BPMNShape_startevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="180.0" y="150.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="usertask1" id="BPMNShape_usertask1">
            <omgdc:Bounds height="55.0" width="105.0" x="371.0" y="140.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="endevent1" id="BPMNShape_endevent1">
            <omgdc:Bounds height="35.0" width="35.0" x="660.0" y="150.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNShape bpmnElement="usertask2" id="BPMNShape_usertask2">
            <omgdc:Bounds height="55.0" width="105.0" x="330.0" y="50.0"></omgdc:Bounds>
          </bpmndi:BPMNShape>
          <bpmndi:BPMNEdge bpmnElement="flow2" id="BPMNEdge_flow2">
            <omgdi:waypoint x="476.0" y="167.0"></omgdi:waypoint>
            <omgdi:waypoint x="660.0" y="167.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="flow3" id="BPMNEdge_flow3">
            <omgdi:waypoint x="197.0" y="150.0"></omgdi:waypoint>
            <omgdi:waypoint x="382.0" y="105.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
          <bpmndi:BPMNEdge bpmnElement="flow4" id="BPMNEdge_flow4">
            <omgdi:waypoint x="382.0" y="105.0"></omgdi:waypoint>
            <omgdi:waypoint x="423.0" y="140.0"></omgdi:waypoint>
          </bpmndi:BPMNEdge>
        </bpmndi:BPMNPlane>
      </bpmndi:BPMNDiagram>
    </definitions>

     

     

     

     

     

    动态配置如下所示:

    <userTask id="usertask1" name="多实例任务" activiti:assignee="${assignee}">

          <multiInstanceLoopCharacteristics isSequential="false" activiti:collection="assigneeList" activiti:elementVariable="assignee">

            <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition>

          </multiInstanceLoopCharacteristics>

    </userTask>

    参数说明:

    activiti:assignee="${assignee}"

    activiti:elementVariable="assignee" 多实例任务依赖上面的配置${assignee}

    activiti:collection="assigneeList" 

    三个参数结合决定了,当前节点的处理人来自assigneeList集合,注意这里是集合信息而不是字符串,所以程序的运行时候变量的赋值,如下所示:

    String[]v={"shareniu1","shareniu2","shareniu3","shareniu4"};

    vars.put("assigneeList",  Arrays.asList(v));

    String taskId="97515";

    demo.getTaskService().complete(taskId,vars);

    ok了,测试一下,确实程序如预期的所示,大功告成。

    1.1.6. 总结

    参数的使用总结

    4.activiti:candidateUsers="shareniu1,shareniu2,shareniu3,shareniu4" 这个节点可以4个人审核。

    5.<loopCardinality>2</loopCardinality> 循环2次结束。

    6.<multiInstanceLoopCharacteristics isSequential="true"> 串行并行的配置。

    7.

     <completionCondition>${nrOfCompletedInstances/nrOfInstances >= 0.25}</completionCondition> 完成条件的配置。

    这里我们还可以得出一个结论:

    如果使用串行方式操作nrOfActiveInstances 变量始终是1,因为并行的时候才会去+1操作。

    1.1.7. 遗留点

    上面的程序已经解决了常用的问题,关于会签、加签、减签、退签、权重配置、自定义通过条件配置(条件自定义通过)

    这些问题,这个章节还没有具体的实现,关于这些问题,由于本章内容有限,我们就后续章节讲解吧。

    未完待续...

    分享牛,分享、我们是快乐的。

    展开全文
  • NLP的四大基本任务

    千次阅读 2019-04-15 08:36:26
    1. 序列标注:分词/POS Tag/NER/语义标注 2. 分类任务:文本分类/情感计算 3. 句子关系判断:Entailment/QA/自然语言推理 4. 生成式任务:机器翻译/文本摘要
  • 任务(task)

    千次阅读 2018-08-15 12:51:31
    任务概述 线程(Thread)是创建并发的底层工具,因此有一定的局限性(不易得到返回值(必须通过创建共享域);异常的捕获和处理也麻烦;同时线程执行完毕后无法再次开启该线程),这些局限性会降低性能同时影响并发...
  • YARN任务提交流程

    千次阅读 2017-07-05 09:52:06
    yarn取代了以前hadoop中jobtracker(后面简写JT)的角色,因为以前JT的 任务过重,负责任务的调度、跟踪、失败重启等过程,而且只能运行mapreduce作业,不支持其他编程模式,这也限制了JT使用范围,而yarn应运而 生...
  • SpringBoot定时任务的使用 一、使用Spring Task 1.引入依赖 首先在我们pom.xml文件中引入spring-boot-starter依赖。 <dependency> <groupId>org.springframework.boot</groupId> <artifactId...
  • SpringBoot-定时任务-集群篇

    万次阅读 2019-11-06 17:40:44
    前面一篇文章(SpringBoot-定时任务)中介绍了如何用SpringBoot框架中的注解方式来实现定时任务,这种方式的好处是不使用第三方的依赖,仅凭几个方便的注解,即可编写一个简单的定时任务处理。 实际开发中为了满足复杂...
  • 现在的web项目中很多场景下都有要执行定时任务的需求,比如说每隔5秒将redis中的统计当天注册用户数持久化到数据库。现在项目中实现这一功能,一般用quartz这一工具框架,但是这个对于一个新手来说比较麻烦,各种查...
  • 一步步学习Linux多任务编程

    万次阅读 多人点赞 2018-02-10 18:51:03
    02、Linux系统调用之I/O操作(文件操作)03、文件描述符的复制:dup(), dup2()多进程实现多任务04、进程的介绍05、Linux可执行文件结构与进程结构06、多进程实现多任务(一):fork()07、多进程实现多任务(二):...
  • SpringBoot重点详解--使用数据库配置Quartz定时任务

    万次阅读 多人点赞 2019-04-01 14:45:04
    创建定时任务实体类 任务实体持久化 创建调度器工厂 TaskUtils工具类 创建定时任务服务类 创建定时任务初始化服务类 创建定时任务实现类 在实际项目开发过程中,定时任务几乎是必不可少的。作为Java程序员用...
  • 详解java定时任务

    万次阅读 多人点赞 2014-06-20 12:08:27
    在我们编程过程中如果需要执行一些简单的定时任务,无须做复杂的控制,我们可以考虑使用JDK中的Timer定时任务来实现。下面LZ就其原理、实例以及Timer缺陷三个方面来解析java Timer定时器。一、简介 在java中一个...
  • win7系统本身无法设置该功能(目前我是不知道哦,...第二部:安装完在扩展屏幕上便会出现任务栏 第三步:在扩展屏下任务栏中右击属性来设置相关的功能。  比如显示Windows按键 这样便解决了两个屏幕双任务栏的功能了。
  • java定时任务实现的几种方式

    万次阅读 多人点赞 2019-08-12 09:59:39
    摘要: 在开发测试工具的应用后台,经常听到同事说要做个定时任务把做日志处理,或者数据清理,包括做些复杂的业务计算逻辑,在选择定时任务的时候,怎么能够快速实现,并且选择一种更适合自己的方式呢?我这里把...
  • Android中的线程池与任务队列

    万次阅读 2012-05-09 21:53:45
    Android中的线程池与任务队列:  在Android手机开发的时候,考虑的资源问题是必须的。当然我们要注重线程的消耗资源的过程,线程在new的时候最消耗内存开销,而在运行的时候远远小于new的时候的内存开销。故我们...
  • SpringBoot几种定时任务的实现方式

    万次阅读 多人点赞 2018-02-01 09:39:16
    原文地址:SpringBoot几种定时任务的实现方式 定时任务实现的几种方式: Timer:这是java自带的java.util.Timer类,这个类允许你调度一个java.util.TimerTask任务。使用这种方式可以让你的程序按照某一个频度执行...
  • **同步任务:**指的是在主线程傻姑娘排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。 **异步任务:**指的是不进入主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 异步执行的运行机制...
  • mysql创建定时任务

    万次阅读 2012-04-26 16:20:24
    一、前言  自 MySQL5.1.6起,增加了一个非常有特色的功能–...更值得 一提的是MySQL的事件调度器可以精确到每秒钟执行一个任务,而操作系统的计划任务(如:Linux下的CRON或Windows下的任务计划)只能精 确到每分钟执
  • win10 任务栏全透明,一键设置(translucentTB)

    万次阅读 热门讨论 2019-03-06 09:34:55
    通过系统个性化设置任务栏为透明,但此方法可能行不通,就算设置成功了也是只有50%的透明度 要使任务栏全透明,只能采用方式2,使用软件translucentTB 方式2 可以实现win10任务栏全透明的工具: 链接:...
1 2 3 4 5 ... 20
收藏数 2,585,254
精华内容 1,034,101
关键字:

任务