2019独角兽企业重金招聘Python工程师标准>>>

由于Spring的事务管理器是通过线程相关的ThreadLocal来保存数据访问基础设施(也即Connection实例),再结合IoC和AOP实现高级声明式事务的功能,所以Spring的事务天然地和线程有着千丝万缕的联系。
   我们知道Web容器本身就是多线程的,Web容器为一个HTTP请求创建一个独立的线程(实际上大多数Web容器采用共享线程池),所以由此请求所牵涉到 的Spring容器中的Bean也是运行于多线程的环境下。在绝大多数情况下,Spring的Bean都是单实例的(singleton),单实例 Bean的最大好处是线程无关性,不存在多线程并发访问的问题,也就是线程安全的。
   一个类能够以单实例的方式运行的前提是“无状态”:即一个类不能拥有状态化的成员变量。我们知道,在传统的编程中,DAO必须持有一个 Connection,而Connection即是状态化的对象。所以传统的DAO不能做成单实例的,每次要用时都必须创建一个新的实例。传统的 Service由于内部包含了若干个有状态的DAO成员变量,所以其本身也是有状态的。
   但是在Spring中,DAO和Service都以单实例的方式存在。Spring是通过ThreadLocal将有状态的变量(如Connection 等)本地线程化,达到另一个层面上的“线程无关”,从而实现线程安全。Spring不遗余力地将有状态的对象无状态化,就是要达到单实例化Bean的目 的。
   由于Spring已经通过ThreadLocal的设施将Bean无状态化,所以Spring中单实例Bean对线程安全问题拥有了一种天生的免疫能力。 不但单实例的Service可以成功运行于多线程环境中,Service本身还可以自由地启动独立线程以执行其他的Service。

启动独立线程调用事务方法

package com.baobaotao.multithread;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Service;
import org.apache.commons.dbcp.BasicDataSource;@Service("userService")
public class UserService extends BaseService {@Autowiredprivate JdbcTemplate jdbcTemplate;@Autowiredprivate ScoreService scoreService;public void logon(String userName) {System.out.println("before userService.updateLastLogonTime method...");updateLastLogonTime(userName);System.out.println("after userService.updateLastLogonTime method...");//scoreService.addScore(userName, 20);//①在同一线程中调用scoreService#addScore()//②在一个新线程中执行scoreService#addScore()Thread myThread = new MyThread(this.scoreService, userName, 20);//使用一个新线程运行myThread.start();}public void updateLastLogonTime(String userName) {String sql = "UPDATE t_user u SET u.last_logon_time = ? WHERE user_name =?";jdbcTemplate.update(sql, System.currentTimeMillis(), userName);}//③负责执行scoreService#addScore()的线程类private class MyThread extends Thread {private ScoreService scoreService;private String userName;private int toAdd;private MyThread(ScoreService scoreService, String userName, int toAdd) {this.scoreService = scoreService;this.userName = userName;this.toAdd = toAdd;}public void run() {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("before scoreService.addScor method...");scoreService.addScore(userName, toAdd);System.out.println("after scoreService.addScor method...");}}
}

将日志级别设置为DEBUG,执行UserService#logon()方法,观察以下输出日志:

引用
before userService.logon method...

//①创建一个事务
Creating new transaction with name [com.baobaotao.multithread.UserService.logon]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver] for JDBC transaction

SQL update affected 1 rows
after userService.updateLastLogonTime method...
Initiating transaction commit

//②提交①处开启的事务
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver]
Releasing JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver] after transaction

Returning JDBC Connection to DataSource
before scoreService.addScor method...

//③创建一个事务
Creating new transaction with name [com.baobaotao.multithread.ScoreService.addScore]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
Acquired Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver] for JDBC transaction

SQL update affected 0 rows
Initiating transaction commit

//④提交③处开启的事务
Committing JDBC transaction on Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver]
Releasing JDBC Connection [jdbc:mysql://localhost:3306/sampledb, UserName=root@localhost , MySQL-AB JDBC Driver] after transaction
Returning JDBC Connection to DataSource
after scoreService.addScor method...

在①处,在主线程(main)执行的UserService#logon()方法的事务启动,在②处,其对应的事务提交。而在子线程(Thread-2)执行的ScoreService#addScore()方法的事务在③处启动,在④处对应的事务提交。
   所以,我们可以得出这样的结论:在相同线程中进行相互嵌套调用的事务方法工作于相同的事务中。如果这些相互嵌套调用的方法工作在不同的线程中,则不同线程下的事务方法工作在独立的事务中。

  注:以上内容摘自《Spring 3.x企业应用开发实战》

转载于:https://my.oschina.net/u/138210/blog/67494

Spring的事务管理难点剖析(4):多线程的困惑相关推荐

  1. Spring的事务管理难点剖析:应用分层的迷惑

    2019独角兽企业重金招聘Python工程师标准>>> Web.Service及DAO三层划分就像西方国家的立法.行政.司法三权分立一样被奉为金 科玉律,甚至有的开发人员认为如果要使 ...

  2. Spring的事务管理难点剖析(1):DAO和事务管理的牵绊

    2019独角兽企业重金招聘Python工程师标准>>> 有些人很少使用Spring而不使用Spring事务管理器的应用,因此常常有人会问:是否用了Spring,就一定要用Spring ...

  3. Spring的事务管理难点剖析(5):联合军种作战的混乱

    2019独角兽企业重金招聘Python工程师标准>>> Spring抽象的DAO体系兼容多种数据访问技术,它们各有特色,各有千秋.像Hibernate是非常优秀的ORM实现方案,但对 ...

  4. 使用动态代理简单模拟一下spring的事务管理

    按照平时写代码的习惯,我们会定义一个service接口 package com.proxy.test; public interface UserService {public void sayHel ...

  5. Spring的事务管理1

    事务的回顾: 事务:逻辑上的一组操作,组成这组事务的各个单元,要么全部成功,要么全部失败 事务的特性:ACID 原子性(Atomicity):事务不可分割 一致性(Consistency):事务执行前 ...

  6. Spring JDBC-Spring事务管理之数据库事务基础知识

    概述 数据库事务的概念 原子性 一致性 隔离性 持久性 数据并发的问题 脏读dirty read 不可重复读unrepeatable read 幻象读 phantom read 幻象读和不可重复度的区 ...

  7. spring教程--事务管理

    Spring的事务管理 1.1 事务: 事务:是逻辑上一组操作,要么全都成功,要么全都失败. 事务特性: ACID: 原子性:事务不可分割 一致性:事务执行的前后,数据完整性保持一致. 隔离性:一个事 ...

  8. batch spring 重复执行_一个3年老javaer竟然连Spring的事务管理都不知道,惊呆了

    1.事务介绍 事务(Transaction),一般是指要做的或所做的事情.在计算机术语中是指访问并可能更新数据库中各种数据项的一个程序执行单元(unit). 这里我们以取钱的例子来讲解:比如你去ATM ...

  9. Spring框架-事务管理注意事项

    转载自 Spring框架-事务管理注意事项 常见事务问题 事务不起作用 可能是配置不起效,如扫描问题 事务自动提交了(批量操作中) 可能是在没事务的情况下,利用了数据库的隐式提交 事务配置说明 通常情 ...

最新文章

  1. 在C#中,变量名前的@符号是什么意思? [重复]
  2. 使用WinSCP上传文件到指定服务器
  3. Bootstrap3系列:下拉菜单
  4. 蜗牛星际网卡驱动_矿渣“蜗牛星际“折腾NAS黑群晖全过程
  5. Mac中Finder是什么?怎么打开?
  6. 还花几个小时整理线缆你就OUT了,VR自由漫步来了
  7. R语言学习笔记-Error in ts(x):对象不是矩阵问题解决
  8. 阵列信号处理基础(一、协方差矩阵)
  9. digester java_Java-Digester:提取节点名称
  10. 中国知网论文free下载的方法
  11. 视频传输协议之MPEG-DASH
  12. 如何快速的开通公众号【原创】功能
  13. 你也还在找程序员外包平台吗?有这几个就足够了!
  14. UI设计中按钮如何设计,常见的按钮设计类型
  15. 广东工业大学第12届ACM程序设计大赛 Problem H: tmk买礼物
  16. ANSYS中按照X坐标提取节点应力值
  17. 法国留学DIY的必备条件和步骤
  18. VAS开启LaFi空投——助力打造区块链数字黄金新生态
  19. Codeforces Round #666 (Div. 2)E Monster Invaders
  20. 计算机三级网络技术笔记(选择题)

热门文章

  1. 公众号管理模块-DouPHP模块化企业网站管理系统v1.6
  2. 苹果cms v8模板 红色动漫影视模板
  3. dos 必知八项命令
  4. 浅谈中国市场带来的问题
  5. 减少HTTP请求之合并图片详解(大型网站优化技术)
  6. WorldCat Search : PHP OCLC Web Services Library
  7. FullCalendar 七:FullCalendar应用——整合农历节气和节日
  8. 人工智障学习笔记——强化学习(4)时间差分方法
  9. strcpy ,strncpy ,strlcpy地用法
  10. Linux远程管理协议(RFB、RDP、Telnet和SSH)