myBatis面试题 如何构建一个线程安全的SqlSession

版权声明:本文为博主原创文章,允许转载,转载时请说明出处 https://blog.csdn.net/qq_41541619/article/details/82528871

利用ThreadLocal获取或者关闭SqlSession对象,实现每一个线程都有自己的一个SqlSession对象。

TheadLocal 线程局部变量

       ThreadLocal 的作用和目的:用于实现线程内的数据共享,即对于相同的程序代码,多个模块在同一个线程中运行时要共享一份数据,而在另外线程中运行时又共享另外一份数据。

       每个线程调用全局 ThreadLocal 对象的 set 方法,在 set 方法中,首先根据当前线程获取当前线程的 ThreadLocalMap 对象,然后往这个 map 中插入一条记录,key 其实是 ThreadLocal 对象,value 是各自的 set 方法传进去的值。也就是每个线程其实都有一份自己独享的 ThreadLocalMap对象,该对象的 Key 是 ThreadLocal 对象,值是用户设置的具体值。在线程结束时可以调用 ThreadLocal.remove()方法,这样会更快释放内存,不调,用也可以,因为线程结束后也可以自动释放相关的 ThreadLocal 变量。

实现:

public class Util {
	private static ThreadLocal<SqlSession> threadLocal = new ThreadLocal<>();
	private static SqlSessionFactory factory = null;
	
	// 构造函数私有
	private Util() {
		
	}
	
	// 读取配置文件
	static {
		try {
			InputStream is = Util.class.getClassLoader().getResourceAsStream("sqlMapConfig.xml");
			factory = new SqlSessionFactoryBuilder().build(is);
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 获取SqlSession
	 * @return
	 */
	public static SqlSession getSqlSession() {
		SqlSession sqlSession = threadLocal.get();  // 从当前线程获取
		if (sqlSession == null) {
			sqlSession = factory.openSession();
			threadLocal.set(sqlSession);  // 将sqlSession与当前线程绑定
		}
		return sqlSession;
	}
	
	/**
	 * 关闭SqlSession
	 */
	public static void close() {
		SqlSession sqlSession = threadLocal.get();  // 从当前线程获取
		if (sqlSession!=null) {
			sqlSession.close();
			threadLocal.remove();
		}
	} 
}

补充:如何实现三个线程,分别输出打印1,2,3

首先创建一个类,用于从ThreadLocal中获取和加入对象

public class ThreadLocalNum{
	private static ThreadLocal<Integer> threadLocal = new ThreadLocal<Integer>() {
		@Override
		protected Integer initialValue() {
			return new Integer(0);
		}
	};
	
	public static Integer get() {
		return threadLocal.get();
	}

	public static void set() {
		threadLocal.set(threadLocal.get()+1);
	}
}

编写测试类

public class ThreadDemo4 implements Runnable{

	static ThreadLocalNum num = new ThreadLocalNum();
	
	public ThreadDemo4(ThreadLocalNum num) {
		this.num = num;
	}
	
	public synchronized void printNum() {
		num.set();
		System.out.println(Thread.currentThread().getName() + ",num:" + num.get());
	}
	
	@Override
	public void run() {
		for (int i = 1;i<=3;i++) {
			printNum();
		}
		
	}

	public static void main(String[] args) {
		ThreadDemo4 tDemo4 = new ThreadDemo4(num);
		Thread thread1 = new Thread(tDemo4);
		Thread thread2 = new Thread(tDemo4);
		Thread thread3 = new Thread(tDemo4);
		thread1.start();
		thread2.start();
		thread3.start();
	}
}

输出结果

猜你喜欢

转载自blog.csdn.net/qq_41541619/article/details/82528871