ThreadLocal笔记

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_37221991/article/details/93922136

ThreadLocal笔记

最近写代码刚好碰到ThreadLocal的小坑,顺便学习了一波ThreadLocal,拿出来分享一下

ThreadLocal什么时候会出现线程不安全的情况呢?

我总结了两种情况

1.记录在 ThreadLocal 中的是一个线程共享的外部对象

https://www.cnblogs.com/qilong853/p/5982878.html

这边文章讲的很好,我就不复制黏贴了,ThreadLocal中保存的是Object对象的一个引用,这样的话,当有其他线程对这个引用指向的对象做修改时,当前线程Thread对象中保存的值也会发生变化

	public class ThreadLocalTest implements Runnable {
	    private Integer count = 0;
		// 一个普通的对象
	    private NumberClass numberClass = new NumberClass();
	    private ThreadLocal<NumberClass> threadLocal = new ThreadLocal();
	    @Override
	    public void run() {
	        numberClass.setNum(++count);
	        threadLocal.set(numberClass);
	        try {
	            Thread.sleep(1000);
	        } catch (InterruptedException e) {
	            e.printStackTrace();
	        }
	        System.out.println("[Thread-" + Thread.currentThread().getId() + "]"+threadLocal.get().getNum());
	
	    }
	}

	 public static void main(String[] args){
	        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
	       ThreadLocalTest thread = new ThreadLocalTest();
	        for (int i =0;i<5;i++ ){
	            fixedThreadPool.execute(thread);
	        }

	//                [Thread-12]5
	//                [Thread-15]5
	//                [Thread-14]5
	//                [Thread-11]5
	//                [Thread-13]5

	// 执行完5个线程中的threadLocal中的值相同
	
	    }

2.引入线程池,线程复用

如果在一个线程被使用完准备回放到线程池中之前,我们没有对记录在数据库中的数据执行清理,那么这部分数据就会被下一个复用该线程的业务看到

	public class ThreadLocalTest2 implements Runnable {
	//    private Integer count = 0;
	    private ThreadLocal<List> threadLocal = new ThreadLocal();
	    @Override
	    public void run() {
	//        Integer count = 0;
	        List<Long> list = threadLocal.get();
	        if (list == null){
	            list = new ArrayList<>();
	            System.out.println("[Thread-" + Thread.currentThread().getId() + "]  init threadLocal");
	        }
	        list.add((long) (1+Math.random()*(10)));
	        threadLocal.set(list);
	        List list2 = threadLocal.get();
	        System.out.println("[Thread-" + Thread.currentThread().getId() + "]"+list);
	
	    }
	}

	  public static void main(String[] args){
	        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
	        ThreadLocalTest2 thread = new ThreadLocalTest2();
	        for (int i =0;i<5;i++ ){
	            fixedThreadPool.execute(thread);
	        }
	
	// 执行结果
	//                [Thread-11]  init threadLocal
	//                [Thread-12]  init threadLocal
	//                [Thread-11][9]
	//                [Thread-12][5]
	//                [Thread-11][9, 1]
	//                [Thread-12][5, 9]
	//                [Thread-11][9, 1, 4]
	
	    }

3.自己踩到的坑

首先碰到的坑是这样的,首先这个selectList是mybatisPlus的方法,执行到这个方法的时无缘无故调用了分页的相关sql,而这个方法里并没有进行分页(pageHelper)的配置。当时我们就想到是线程串了,当前线程使用了其他线程的分页配置。但是我们通过观察PageHelper的源码发现,

    protected static final ThreadLocal<Page> LOCAL_PAGE = new ThreadLocal<Page>();

配置是放在ThreadLocal里面的,而且分页查询执行完毕,会调用销毁ThreadLocal的方法,不会出现第二种问题,

    public static void clearLocalPage() {
            LOCAL_PAGE.remove();
    }

并且存的Page对象是new的变量,也不会出现第一种问题。
正常情况不会出现线程不安全的情况。

	public static <E> Page<E> startPage(int pageNum, int pageSize, boolean count, Boolean reasonable, Boolean pageSizeZero) {
	      Page<E> page = new Page<E>(pageNum, pageSize, count);
        	 ...
    }

坑在这里
图
写代码的时候一开始设置了pageHelper,后面进行了if语句,没有执行下面的sql,导致page信息没有被销毁,当这个线程被复用的时候,就会以为要分页了

展开阅读全文

threadlocal报错

08-08

package com.yinbo.tbms.jljiao;rnrnimport org.hibernate.HibernateException;rnimport org.hibernate.Session;rnimport org.hibernate.cfg.Configuration;rnpublic class HibernateSessionFactory rnprivate static String CONFIG_FILE_LOCATION="/hibernate.cfg.xml";rnprivate static final ThreadLocalthredLocal=new ThreadLocal();rnprivate static Configuration configuration=new Configuration();rnprivate static org.hibernate.SessionFactory sessionFactory;rnprivate static String configFile=CONFIG_FILE_LOCATION;rnstaticrn tryrn configuration.configure(configFile);rn sessionFactory=configuration.buildSessionFactory();rn catch(Exception e)rn System.err.println("%%%% Error Creating SessionFactory %%%%");rn e.printStackTrace();rn rnrnprivate HibernateSessionFactory()rn rnrnpublic static Session getSession() throws HibernateExceptionrnrn Session session=(Session)threadLocal.get();rn if(session==null||!session.isOpen())rn rn rebuildSessionFactory();rn rn session=(sessionFactory!=null)?sessionFactory.openSession():null;rn rn threadLocal.set(session);rn return session;rn rnpublic static void rebuildSessionFactory()rn rn tryrn configuration.configure(configFile);rn sessionFactory=configuration.buildSessionFactory();rn catch(Exception e)rn System.err.println("%%%% Error Creating SessionFactory %%%%");rn e.printStackTrace();rn rn rnpublic static void closeSession() throws HibernateExceptionrn rn Session session=(Session)threadLocal.get();rn threadLocal.set(null);rn if(session!=null)rn rn session.close();rn rnrnpublic static org.hibernate.SessionFactory getSessionFactory()rn return sessionFactory;rnrnpublic static void setConfigFile(String conFile)rn HibernateSessionFactory.configFile=configFile;rn sessionFactory=null;rnrnpublic static Configuration getConfiguration()rn return configuration;rnrnrn 论坛

QueryRunner和ThreadLocal

06-26

<p>n <span style="color:#333333;">本课程详细讲解了以下内容:<br />n    1.jsp环境搭建及入门、虚拟路径和虚拟主机、JSP执行流程<br /><br />n    2.使用Eclipse快速开发JSP、编码问题、JSP页面元素以及request对象、使用request对象实现注册示例<br /><br />n    3.请求方式的编码问题、response、请求转发和重定向、cookie、session执行机制、session共享问题<br /><br />n     4.session与cookie问题及application、cookie补充说明及四种范围对象作用域<br /><br />n     5.JDBC原理及使用Statement访问数据库、使用JDBC切换数据库以及PreparedStatement的使用、Statement与PreparedStatement的区别<br /><br />n     6.JDBC调用存储过程和存储函数、JDBC处理大文本CLOB及二进制BLOB类型数据<br /><br />n     7.JSP访问数据库、JavaBean(封装数据和封装业务逻辑)<br /><br />n     8.MVC模式与Servlet执行流程、Servlet25与Servlet30的使用、ServletAPI详解与源码分析<br /><br />n     9.MVC案例、三层架构详解、乱码问题以及三层代码流程解析、完善Service和Dao、完善View、优化用户体验、优化三层(加入接口和DBUtil)<br /><br />n    1 0.Web调试及bug修复、分页SQL(Oracle、MySQL、SQLSERVER)<br /><br />n     11.分页业务逻辑层和数据访问层Service、Dao、分页表示层Jsp、Servlet<br /><br />n     12.文件上传及注意问题、控制文件上传类型和大小、下载、各浏览器下载乱码问题<br /><br />n     13.EL表达式语法、点操作符和中括号操作符、EL运算、隐式对象、JSTL基础及set、out、remove<br /><br />n     14.过滤器、过滤器通配符、过滤器链、监听器<br /><br />n     15.session绑定解绑、钝化活化<br /><br />n     16.以及Ajax的各种应用<br /></span>n</p>n<p>n <span style="color:#333333;"><br /></span>n</p>n<p>n <span style="color:#333333;">     17. Idea环境下的Java Web开发</span>n</p>

没有更多推荐了,返回首页