快速理解为何要使用ThreadLocal?

问题场景一:高并发的时候,我们在调用一些公有的对象资源的时候,会有线程安全问题。

解决线程安全问题
方法一:对全局变量进行加锁。缺点是其他线程要使用的话,就必须等待,耗时。
方法二:把全局变量变成局部方法变量。这样就解决了线程安全问题。

问题场景二:我既要解决安全问题,我又要实现全局共享呢。

很多地方我们都需要这样做。比如:我们需要获取数据库连接的时候,我们会单独封装一个方法叫getConnection()这个方法用来获取connect
,那么我们还会封装几个方法
commit()提交事物,
rollback()回滚事物的方法,
closeConnection()关闭连接方法。
这几个方法自然需要共用一个connection对象才能对当前连接进行操作。

那么如何共用呢?全局变量会造成线程安全问题,加锁会对性能有影响,设置为局部变量,那么就不能在各个方法中使用了。 我们现在需要一个:既能够共用,但又不是全局变量线程安全的东西,仿佛是局部定义的变量能够在各个方法中重用一样。

这个时候就可以使用ThreadLocal来解决既能够共用,又不会造成线程安全的问题。**

至于ThreadLocal怎么用,网上很多例子,我也看了,但是看来看去都没说为什么要用,只说了怎么用,怎么用的博客太多了。我这里就简单的贴一下代码案例:

package day02;

import java.io.FileInputStream;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Properties;

import org.apache.commons.dbcp.BasicDataSource;

/**
 * 该类用于维护数据库连接
 * @author tarena
 *
 */
public class DBUtil {
	/*
	 * ThreadLocal用于线程跨方法共享数据使用
	 
	 * TheaddLocal内部有一个Map,key为要共
	 * 享数据的线程本身,value就是其需要共享的数据。
	 */
	private static ThreadLocal<Connection> tl;
	private static BasicDataSource dataSource;
	private static String className;
	private static String url;
	private static String username;
	private static String password;
	static{
		tl = new ThreadLocal<Connection>();
		/*
		 * properties文件
		 * properties文件常被用来做配置文件,
		 * 结构简单。
		 */
		
		try{
			Properties pro = new Properties();
			pro.load(new FileInputStream("src/main/java/day02/config.properties"));
			className = pro.getProperty("classname");
			url = pro.getProperty("url");
			username = pro.getProperty("username");
			password = pro.getProperty("password");
			int maxActive = Integer.parseInt(pro.getProperty("maxactive"));
			long maxWait = Long.parseLong(pro.getProperty("maxwait"));

			//初始化连接池
			dataSource = new BasicDataSource();
			dataSource.setDriverClassName(className);
			dataSource.setUrl(url);
			dataSource.setUsername(username);
			dataSource.setPassword(password);
			
			//设置最大连接
			dataSource.setMaxActive(maxActive);
			//设置最大等待时间
			dataSource.setMaxWait(maxWait);
			
		}catch(Exception e){
			e.printStackTrace();
		}

	}
	/**
	 * 获取数据库连接
	 * @return
	 * @throws SQLException 
	 * @throws ClassNotFoundException 
	 */
	public static  Connection getConnection() throws SQLException, ClassNotFoundException{
			Connection connection = dataSource.getConnection();
//			Class.forName(className);
//			Connection connection = DriverManager.getConnection(url,username,password);
			tl.set(connection);
			return connection;
	}
	/**
	 * 关闭数据库
	 * @param conn
	 */
	public static void closeConnection(){
		try{
			//关闭连接前,提交事务
			TransCommit();
			//如果是使用连接池获得的连接,那么调用该连接的close方法不会关闭连接,只是表示当前连接使用完毕,空闲。
			Connection connection = tl.get();
			//删除当前线程所存放的连接
			tl.remove();
			if(connection != null){
				connection.close();
			}
		}catch(Exception e){
			e.printStackTrace();
		}
	}
	/*
	 * 开启事务
	 */
	public static void TransBegin(){
		
		try {
			tl.get().setAutoCommit(false);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//回滚事务
	public static void TransRollBack(){
		try {
			tl.get().rollback();
			tl.get().setAutoCommit(true);
		} catch (SQLException e) {
			e.printStackTrace();
		}
	}
	//提交事务
	public static void TransCommit(){
		try {
			tl.get().commit();
			tl.get().setAutoCommit(true);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值