1.默认流程实例:假设有以下流程:

以上包含一个用户任务,服务任务,及定时时间流程。由于服务任务是自动执行的,所以完成用户任务和检验地址服务会在同一个事务中,就会导致当校验地址服务出现异常时,事务回滚,用户任务又会回到数据库中(act_run_task).
2.异步执行
有时我们需要自己控制事务边界,这样就可以将业务逻辑包裹在一起,这时就需要异步执行了。如下实例:

以上是包含用户任务,服务任务及接受任务的流程。此处的流程中用户任务在一个事务中,服务任务和接受任务在另一个任务中,故当产生发票出现异常,不会引起用户任务的回滚。这里想要实现的是,让activiti去完成用户任务,提交事务,返回给调用者应用;然后在后台线程中,异步生成发票;生成发票过程由job执行器来监控执行。所以后面的场景,当我们到达“generate invoice”任务,我们为activiti创建一个稍后执行的job消息,并把它保存在数据库中,Job会被job执行器获取并执行。
使用异步执行时,需要使用activiti:asyn="true"扩展,如下:
<serviceTask id="service1" name="Generate Invoice" activiti:class="my.custom.Delegate" activiti:async="true" />
activiti:async can be specified on the following BPMN task types: task, serviceTask, scriptTask, businessRuleTask, sendTask, receiveTask, userTask, subProcess, callActivity
On a userTask, receiveTask or other wait states, the async continuation allows us to execute the start execution listeners in a separate thread/transaction.(对于userTAsk,recieveTask及需要存在等待状态的任务,异步是让执行监听器在一个线程或事务中执行)
3.排他任务
从activiti5.9开始,JobExcutor能保证同一个流程实例中的Job不会并发执行。activiti默认就是排他任务。因为JobExecutor会保证在任何时候获取一个流程实例的排他任务时,都会将同一流程实例的其他排他任务都取出来,放在同一个工作线程中顺序执行。

以上包含一个并行网关和三个异步执行的服务任务。这样会添加三个job到数据库中,他就可以被jobExecutor执行了。
由于三个服务任务都是异步的,故可能出现三个job被jobExecute同时获取执行,最终导致三个提交事务同时汇聚时重叠,又由于事务是互相不可见的,所以他们都在等待其他分支任务,无法继续执行。
排他JOb:可以通过activiti:exclusive="true"设置排他任务。
异步执行总结:
a. 排他job和非排他job的区别:前者即JobExecutor会保证在任何时候获取一个流程实例的排他任务时,都会将同一流程实例的其他排他任务都取出来,放在同一个工作线程中顺序执行。 后者即JobExecutor会把job放到线程池中来执行,会出现每job会被分配给一个线程来执行,出现线程并发。
b.