ThreadLocal

  在"事务传递Connection"参数案例中,我们必须传递Connection对象,才可以完成整个事务操作.如果不传递参数,是否可以完成?在JDK中给我们提供了一个工具类ThreadLocal.此类可以在一个线程中共享数据

java.lang.ThreadLocal:该类提供了线程局部(thread-local)变量,用于在当前线程中共享数据.

ThreadLocal

java.lang.ThreadLocal该类提供了线程局部(thread-local)变量,用于在当前线程中共享数据,ThreadLocal工具类底层就是一个相当于一个Map,key存放的当前线程,value存放需要共享的数据.

package com.qingmu;

/**
* @Auther:qingmu
* @Description:脚踏实地,只为出人头地
* @Date:Created in 16:08 2019/5/25
*/
public class ThreadLocalTest {
public static void main(String[] args) {
ThreadLocal<String> stringThreadLocal = new ThreadLocal<>();
stringThreadLocal.set("青木");
System.out.println(stringThreadLocal.get()); new Thread(()->
System.out.println(stringThreadLocal.get())).start();
}
}

结果为:

总结:向ThreadLocal中添加的数据只能在当前线程中使用.

小案例的应用:

工具类

public class C3P0Utils {
//创建一个C3P0的连接池对象(使用c3p0-config.xml中default-config标签中对应的参数)
public static DataSource ds = new ComboPooledDataSource();
//给当前线程绑定 连接
private static ThreadLocal<Connection> local = new ThreadLocal<Connection>();
/**
* 获得一个连接
*/
public static Connection getConnection(){
try {
    //#1从当前线程中, 获得已经绑定的连接
service层
Connection conn = local.get();
if(conn == null){
        //#2 第一次获得,绑定内容 – 从连接池获得
conn = ds.getConnection();
          //#3 将连接存 ThreadLocal
local.set(conn);
}
return conn; //获得连接
} catch (Exception e) {
      //将编译时异常 转换 运行时 , 以后开发中运行时异常使用比较多的。
throw new RuntimeException(e);
/*
类与类之间 进行数据交换时,可以使用return返回值。也可以使用自定义异常返回值,调用者try{}
catch(e){ e.getMessage() 获得需要的数据}
此处可以编写自定义异常。
*/
//throw new MyConnectionException(e);
}
}
}

service层

public class AccountService {
/**
* 事务管理方式:向下传递Connection。有侵入性。使用DBUtils
* 业务层事务管理转账的方法
* @param from
* @param to
* @param money
*/
public void transfer(String from, String to, double money) {
//调用dao层
AccountDao accountDao = new AccountDao();
//DBUtils进行事务处理的原理,是在Service层获得连接,以保证事务处理过程中的Connection对象为同一个Connection。
//因为必须保证连接为同一个连接,所以在业务层获得连接,再将连接传递到持久层,代码具有侵入性。
//DBUtils使用的方法
Connection conn = null;
try {
//获得连接
conn = C3P0Utils.getConnection();
//设置事务不自动提交
conn.setAutoCommit(false);
//调用持久层
accountDao.outMoney(from,money);
//如果有异常
//int a = 1 / 0 ;
accountDao.inMoney(to,money);
//提交事务,并安静的关闭连接
DbUtils.commitAndCloseQuietly(conn);
} catch (SQLException e) {
//有异常出现时,回滚事务,并安静的关闭连接
DbUtils.rollbackAndCloseQuietly(conn);
e.printStackTrace();
}
}
}

dao层

public class AccountDao {
/**
* 付款方法
* @param from 付款人
* @param money 金额
*/
public void outMoney(String from, double money) {
QueryRunner qr = new QueryRunner();
try {
Connection conn = C3P0Utils.getConnection();
String sql = "update account set money = money - ? where name = ?";
qr.update(conn, sql, money,from);
} catch (SQLException e) {
e.printStackTrace();
}
}
/**
* 收款方法
* @param to 收款人
* @param money 金额
*/
public void inMoney(String to, double money) {
QueryRunner qr = new QueryRunner();
try {
Connection conn = C3P0Utils.getConnection();
String sql = "update account set money = money + ? where name = ?";
qr.update(conn, sql, money,to);
} catch (SQLException e) {
e.printStackTrace();
}
}
}

ThreadLocal(在一个线程中共享数据)的更多相关文章

  1. Disruptor 线程间共享数据无需竞争

    队列的作用是缓冲 缓冲到 队列的空间里.. 线程间共享数据无需竞争 原文 地址  作者  Trisha   译者:李同杰 LMAX Disruptor 是一个开源的并发框架,并获得2011 Duke’ ...

  2. 参数在一个线程中各个函数之间互相传递的问题(ThreadLocal)

    ThreadLocal最常用的地方就是为每个线程绑定一个数据库连接,HTTP请求,用户身份信息等,这样一个线程的所有调用到的处理函数都可以非常方便地访问这些资源. 一个ThreadLocal变量虽然是 ...

  3. 详解 Qt 线程间共享数据(用信号槽方式)

    使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...

  4. Qt学习:线程间共享数据(使用信号槽传递数据,必须提前使用qRegisterMetaType来注册参数的类型)

    Qt线程间共享数据主要有两种方式: 使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的: 使用singal/slot机制,把数据 ...

  5. 使用ThreadLocal在线程内部传递数据

    最近在项目中使用到了JDK提供的线程池,遇到了在多线程环境下在线程内部共享数据的问题 使用ThreadLocal 来解决线程内部共享数据的问题 定义BO package com.unicom.uclo ...

  6. 详解 Qt 线程间共享数据(使用signal/slot传递数据,线程间传递信号会立刻返回,但也可通过connect改变)

    使用共享内存.即使用一个两个线程都能够共享的变量(如全局变量),这样两个线程都能够访问和修改该变量,从而达到共享数据的目的. Qt 线程间共享数据是本文介绍的内容,多的不说,先来啃内容.Qt线程间共享 ...

  7. Java基础-线程操作共享数据的安全问题

    Java基础-线程操作共享数据的安全问题 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.引发线程安全问题 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运 ...

  8. JAVA多线程提高四:多个线程之间共享数据的方式

    多个线程访问共享对象和数据的方式 如果每个线程执行的代码相同,可以使用同一个Runnable对象,这个Runnable对象中有那个共享数据,例如,买票系统就可以这么做. 如果每个线程执行的代码不同,这 ...

  9. Java并发基础09. 多个线程间共享数据问题

    先看一个多线程间共享数据的问题: 设计四个线程,其中两个线程每次对data增加1,另外两个线程每次对data减少1. 从问题来看,很明显涉及到了线程间通数据的共享,四个线程共享一个 data,共同操作 ...

随机推荐

  1. c#.net EF DB FIRST 添加新的模型

    双击.edmx ,右键-从数据库更新模型,在“添加”里选择新表.

  2. replace into 详解 update mysql

    转replace 与 update 区分本文主要对比一下 Sqlite 中的 replace 语句和 update 语句 . 在本例中使用如下数据库表:   图1 该表的表名为student, 存储学 ...

  3. 本地win下JConsole监控远程linux下的JVM

    环境:服务器端: Linux + jdk1.7.0_75 + tomcat 7本地: Win + jdk1.7.0_55 一.修改/etc/hosts文件 hostname -i 如果显示127.0. ...

  4. [ARM-Linux开发]linux dmesg命令参数及用法详解(linux显示开机信息命令)

    功能说明:显示开机信息.语 法:dmesg [-cn][-s <缓冲区大小>]补充说明:kernel会将开机信息存储在ring buffer中.您若是开机时来不及查看信息,可利用dmesg ...

  5. 【bat】【windows】win10查看所有wifi密码

    win10的可以,win7的好像不行 @echo off & setlocal EnableDelayedExpansion title 查看所有wifi和密码 for /f "us ...

  6. count_if 功能模板

    count_if 功能模板 template <class InputIterator, class UnaryPredicate> typename iterator_traits< ...

  7. C 语言 基础篇

    1.机器语言 2.汇编语言 3.高级语言:C.C++.Java(基于虚拟机) C语言开发:Unix,Linux,Mac OS,iOS,Android,Windows,Ubuntu 开发环境:visua ...

  8. hadoop2.x大数据视频教程(十二天学会)

  9. 「UER#2」谣言的传播

    「UER#2」谣言的传播 写了个乱搞,怎么莫名其妙就AC了,这...,之后又想了30min结合题解终于会证了. 首先最大值比较简单,记 \(f_i\) 为第 \(i\) 个点能到达的点数,上界 \(\ ...

  10. docker stack 部署 mssql

    =============================================== 2019/12/8_第1次修改                       ccb_warlock == ...