java多线程ThreadLocal使用小结

      ThreadLocal,很多地方叫做线程本地变量,也有些地方叫做线程本地存储,它用于保存某个线程共享变量:对于同一个static ThreadLocal,不同线程只能从中get,set,remove自己的变量,而不会影响其他线程的变量。传统的jdbc技术连接数据库是这样的:

class ConnectionManager {
     
    private static Connection connect = null;
     
    public static Connection openConnection() {
        if(connect == null){
            connect = DriverManager.getConnection();
        }
        return connect;
    }
     
    public static void closeConnection() {
        if(connect!=null)
            connect.close();
    }
}

      这种连接数据库方式在单线程是没有问题的,但是在多线程同步过程中就会存在多次创建、关闭connect的过程。因此在这个地方可以使用多线程解决这个问题。

1.多线程的写法:

package com.shopping.util;

import java.sql.Connection;
import java.sql.SQLException;

import javax.sql.DataSource;

import com.mchange.v2.c3p0.ComboPooledDataSource;

/**
 * 创建数据库连接池
 */
public class JDBCUtils {
	// 创建一个ThreadLoacl对象,用当前线程作为key
	private static ThreadLocal<Connection> tc = new ThreadLocal<Connection>();
	// 读取的是C3P0-config默认配置创建数据库连接池对象
	private static DataSource ds = new ComboPooledDataSource();

	// 获取数据库连接池对象
	public static DataSource getDataSource() {
		return ds;
	}

	// 从连接池中获取连接
	public static Connection getConnection() throws SQLException {
		Connection conn = tc.get();
		if (conn == null) {
			conn = ds.getConnection();
			// 将conn存放到集合tc中
			tc.set(conn);
			System.out.println("首次创建连接:" + conn);
		}
		return conn;
	}

	// 开启事务
	public static void startTransaction() {
		try {
			// 获取连接
			Connection conn = getConnection();
			// 开启事务
			/*
			 * setAutoCommit总的来说就是保持数据的完整性,一个系统的更新操作可能要涉及多张表,需多个SQL语句进行操作
			 * 循环里连续的进行插入操作,如果你在开始时设置了:conn.setAutoCommit(false);
			 * 最后才进行conn.commit(),这样你即使插入的时候报错,修改的内容也不会提交到数据库,
			 */
			conn.setAutoCommit(false);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	public static void commit() {
		try {
			Connection conn = tc.get();
			if (conn != null) {
				conn.commit();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}	
}

C3P0-config文件配置的是数据库的信息

<?xml version="1.0" encoding="UTF-8"?>
<c3p0-config>
	<!-- 默认配置,当使用ComboPooledDataSource无参构造器时,使用的就是这个配置 -->
	<default-config>
		<!-- 基本配置 -->
		<property name="jdbcUrl">jdbc:mysql://localhost:3306/数据库表名?characterEncoding=UTF-8
		</property>
		<property name="driverClass">com.mysql.jdbc.Driver</property>
		<property name="user">user</property>
		<property name="password">pass</property>
		<!-- 每次增量,当需要创建Connection对象时,一次创建几个 -->
		<property name="acquireIncrement">3</property>
		<!-- 当创建池对象后,池中应该有几个Connection对象 -->
		<property name="initialPoolSize">10</property>
		<!-- 池中最少Connection个数,如果少于这个值,就会创建Connection -->
		<property name="minPoolSize">2</property>
		<!-- 池中最大连接个数 -->
		<property name="maxPoolSize">10</property>
	</default-config>
</c3p0-config>

ps:上一个中的conn.setAutoCommit(false);这句话可以与conn.commit()防止多张表数据修改时候错误的信息写入数据库。

2. ThreadLocal源码解析

ThreadLocal类提供的几个方法:

1

2

3

4

public T get() { }

public void set(T value) { }

public void remove() { }

protected T initialValue() { }

可以参考 https://www.cnblogs.com/dolphin0520/p/3920407.html这篇文章

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值