zl程序教程

您现在的位置是:首页 >  硬件

当前栏目

软件事务内存导论(八)提交和回滚事件

内存事件软件事务 提交 回滚 导论
2023-09-11 14:16:12 时间
提交和回滚事件

Java的try-catch-finally语法结构不但使我们可以安全地处理异常,还能够在程序抛出异常时选择性地执行一些代码。同样地,我们 也可以控制程序在事务成功提交之后去执行某段代码,而当事务回滚时则去执行另一段代码。StmUtils中的deferred()和 compensatiing()这两个函数分别提供了上述功能。特别地,在实现事务的过程中,为保证事务能顺利完成,我们通常会加入一些带副作用的逻辑, 而deferred()函数则是一个执行所有这部分逻辑的绝佳地点。


Java中的提交和回滚事件

我们可以把想要在事务成功完成之后执行的代码放在Runnable接口实现部分的代码块中,并将其作为参数传给StmUtils的 deferred()函数。同样地,我们也可以把想要在事务失败之后执行的代码封装在Runnable接口中传给compensating()函数。由于 这两个函数必须在事务的环境下运行,所以我们只有在automically()函数的函数体中才能调用他们。

public class Counter {

 private final Ref Integer value = new Ref Integer 

 public void decrement() {

 new Atomic Integer () {

 public Integer atomically() {

 deferred(new Runnable() {

 public void run() {

 System.out.println(

 "Transaction completed...send email, log, etc.");

 compensating(new Runnable() {

 public void run() {

 System.out.println("Transaction aborted...hold the phone");

 if(value.get() = 0)

 throw new RuntimeException("Operation not allowed");

 value.swap(value.get() - 1);

 return value.get();

 }.execute();

在Counter类的定义代码中我们看到,Counter类仅含有一个名为decrement()的实例方法。在这个方法中,我们继承了 Atomic类并实现了atomically()函数。在前面的例子中,我们都仅仅是简单地把事务的逻辑代码放在这个位置。而现在,除了原有的逻辑代码之 外,我们把事务成功和事务回滚之后要执行的代码也放到了atomically()里面。下面让我们构建一个简单的测试用例来验证一下Counter的功 能:

package com.agiledeveloper.pcj;

public class UseCounter {

 public static void main(final String[] args) {

 Counter counter = new Counter();

 counter.decrement();

 System.out.println("Lets try again...");

 try {

 counter.decrement();

 } catch(Exception ex) {

 System.out.println(ex.getMessage());

通过运行UseCounter,我们可以清楚地观察到事务成功完成和失败时程序的执行逻辑:

Transaction aborted...hold the phone

Transaction completed...send email, log, etc.

Lets try again...

Transaction aborted...hold the phone

Operation not allowed

当第一次调用decrement()函数并成功完成事务之后,封装在deferred()函数内的代码逻辑将被执行。而当我们第二次调用 decrement()时,由于事务执行过程中抛出了异常,所以事务将被回滚,而封装在compensating()函数内的代码也将被执行。最后我们需 要注意的是,输出结果中最顶部的那个非预期的重试是由我们之前在6.9节中曾讨论过的默认优化设置所导致的。

deferred()函数是一个执行事务收尾工作以便使其效果固化的绝佳地点,所以我们可以在里面随便进行打印、显示消息、发布通知以及提交数据库 事务等操作。如果我们在事务之外有什么遗留的工作待完成,那么这个函数无疑是最好的完成地点。与deferred()类似的 是,compensating()函数是记录事务失败信息的好地方。此外,如果我们之前已经将非托管对象(即那些没有使用Akka Ref进行管理的对象)与托管对象混杂在一起的话,那么这里也是纠正这一错误的合适地点——但是由于这种做法太容易出错,所以请你最好避免采用这样的设计 思路。

Scala中的提交和回滚事件

在Scala中,我们处理提交和回滚事件的方式与Java基本相同,唯一区别就是在Scala中我们可以将闭包/函数值直接传递给deferred()和compensating()。下面让我们将Counter类由Java转译成Scala。

class Counter {

 private val value = Ref(1)

 def decrement() = {

 atomic {

 deferred { println("Transaction completed...send email, log, etc.") }

 compensating { println("Transaction aborted...hold the phone") }

 if(value.get() = 0)

 throw new RuntimeException("Operation not allowed")

 value.swap(value.get() - 1)

 value.get()

在上面的代码中,我们将事务运行成功时所要执行的那部分代码封装在一个闭包中,然后将其作为参数传递给deferred()函数。类似地,事务回滚 时所要执行的代码也被作为一个闭包赋给了compensating()函数。与此同时,这两个函数又与事务逻辑代码一起被置于表示atomic()函数的 闭包当中。这段代码再次彰显了Scala在语法上简洁明了的特征。下面让我们将UseConuter类也从Java转译成Scala:

package com.agiledeveloper.pcj

object UseCounter {

 def main(args : Array[String]) : Unit = {

 val counter = new Counter()

 counter.decrement()

 println("Lets try again...")

 try {

 counter.decrement()

 } catch {

 case ex = println(ex.getMessage())

如下所示,Scala版代码的执行结果与Java版的结果是完全相同的:

Transaction aborted...hold the phone Transaction completed...send email, log, etc. Lets try again... Transaction aborted...hold the phone Operation not allowed


文章转自 并发编程网-ifeve.com


CleanMyMac X稳定版苹果电脑磁盘内存清理软件 Mac电脑用的时间久了,Mac用户尤其是MacBook用户会经常收到“磁盘几乎已满”的提示,如何解决这个问题,当我们使用苹果MAC一段时间后,就会有大量的垃圾文件占用磁盘空间,例如系统缓存文件、应用程序缓存文件、备份和重复文件、旧版的应用程序及其部件等,为了不影响电脑的后续使用,我们需要经常清理磁盘空间,这里分享一个处理磁盘空间不足提示的小方法。CleanMyMac X下载:http://t.csdn.cn/ye9sT
Android 7.1 内置“一键清理内存”功能,专治流氓勒索软件 本文讲的是Android 7.1 内置“一键清理内存”功能,专治流氓勒索软件,在打击Android恶意勒索软件上,Google最近迈出了一大步,它推出的一项隐藏新功能,让用户在中招后还能保持对设备的控制权。
软件事务内存导论(七)阻塞事务 阻塞事务——有意识地等待 我们经常会遇到这样一种情况,即某事务T能否成功完成依赖于某个变量是否发生了变化,并且由于这种原因所引起的事务运行失败也可能只是暂时性的。作 为对这种暂时性失败的响应,我们可能会返回一个错误码并告诉事务T等待一段时间之后再重试。