多线程下,解决银行转账,不同线程对事务操作的原子性:
用到了ThrealLocal类,来实现。
ThrealLocal中是map集合,存储的是map(thread,T):键标识是当前线程,T标识泛型值。功能:能够唯一标识一个线程,不同线程可以有不同标识。这样可以保证在转账过程中,只能在同一线程中进行事务的操作。保证不同线程之间,事务的操作是隔离的
定义工具类:
public class DbUtilsDataSource {
private static DruidDataSource druidDataSource= null;
public static ThreadLocal<Connection> threadLocal=new ThreadLocal<>();
/*放入静态代码块中,在调用静态方法getDataResource的时候触发类加载*/
static {
try {
/*从配置文件中获取*/
Properties properties = new Properties();
/*获取配置文件流对象*/
InputStream is = DbUtilsDataSource.class.getClassLoader().getResourceAsStream("com/xzq/druidutils/druidmess.properties");
/*加载配置文件*/
properties.load(is);
is.close();
/*利用工厂方式获取一个连接池对象*/
druidDataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties);
} catch (Exception e) {
e.printStackTrace();
}
}
public static Connection getConnection() {
/*刚开始threadlocal中是没有值的,为null,所以*/
Connection connection = threadLocal.get();
if(connection ==null)
{
try {
//获取连接池对象,就当如到threadlical对象中。
connection = getDataResource().getConnection();
/*把connection放入threadlocal*/
threadLocal.set(connection);
} catch (SQLException e) {
e.printStackTrace();
}
}
return connection;
}
public static DataSource getDataResource(){
return druidDataSource;
}
/*开启事务*/
public static void start() throws SQLException {
Connection connection = getConnection();
if(connection!=null){
connection.setAutoCommit(false);
}
}
/*提交事务*/
public static void commit() throws SQLException {
Connection connection = getConnection();
if(connection!=null){
connection.commit();
}
}
/*回滚事务*/
public static void rollback() throws SQLException {
Connection connection = getConnection();
if (connection != null) {
connection.rollback();
}
}
/*当前线程,事务操作完成,关闭连接,解绑(也就是将threadlocal中的值移除掉)*/
public static void close() throws SQLException {
Connection connection = getConnection();
if (connection != null) {
connection.close();
threadLocal.remove();
}
}
}
转账:
public void sendmoney(String money,String fcard,String tcard ) {
/*获取连接*/
Connection connection = DbUtilsDataSource.getConnection();
try {
/*开启事务*/
DbUtilsDataSource.start();
td.addMoney(money,tcard);
td.subtracMoney(money,fcard);
//提交事务
DbUtilsDataSource.commit();
} catch (Exception e) {
try {
/*事务回滚*/
DbUtilsDataSource.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}finally {
try {
DbUtilsDataSource.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}