zoukankan      html  css  js  c++  java
  • ThreadLocal的使用

    ThreadLocal 的作用,它可以解决多线程的数据安全问题

    ThreadLocal 它可以给当前线程关联一个数据(可以是普通变量,可以是对象,也可以是数组,集合)

    ThreadLocal 的特点:

        1、ThreadLocal 可以为当前线程关联一个数据。(它可以像 Map 一样存取数据,key 为当前线程)
        2、每一个 ThreadLocal 对象,只能为当前线程关联一个数据,如果要为当前线程关联多个数据,就需要使用多个
    ThreadLocal 对象实例。
        3、每个 ThreadLocal 对象实例定义的时候,一般都是 static 类型
        4、ThreadLocal 中保存数据,在线程销毁后。会由 JVM 虚拟自动释放。

    我们在不使用threadLocal的时候使用数据关联是这样的:

    public class ThreadLocal  {
        private static Map<String,Object> data = new Hashtable<String, Object>();
        private static Random random = new Random();
    
        public static class Task implements Runnable{
            @Override
            public void run() {
                String name = Thread.currentThread().getName();
                Integer i = random.nextInt(1000);
                System.out.println("在线程["+name+"]中生成的随机数是"+i);
                data.put(name,i);
                try {
                    Thread.sleep(300);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                Object o = data.get(name);
                System.out.println("在线程中["+name+"]快结束时取值的结果是:"+o);
    
    
    
            }
        }
    
    
        public static void main(String [] args){
            for (int i = 0; i < 3; i++) {
                new Thread(new Task()).start();
            }
        }
    
    }
    手动实现ThreadLocal
    public class ThreadLocalOne {
        private static Map<String,Object> data = new Hashtable<String, Object>();
        private static Random random = new Random();
    
        public static class Task implements Runnable{
    
            @Override
            public void run() {
                // 在 Run 方法中,随机生成一个变量(线程要关联的数据),然后以当前线程名为 key 保存到 map 中
                Integer i =  random.nextInt();
                // 获取当前线程名
                String name = Thread.currentThread().getName();
                System.out.println("线程["+name+"]生成的随机数是: "+i);
                data.put(name,i);
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                // 在 Run 方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作
                Object o = data.get(name);
                System.out.println("线程["+name+"]快结束时取出关联的数据是"+o);
    
            }
        }
    
        public static void main(String[] args) {
            for (int i = 0; i <3 ; i++) {
                new Thread(new Task()).start();
            }
        }
    }

    上面是我们的手动实现的ThreadLocal类的实现

    使用ThreadLocal进行线程关联

    public class ThreadLocalOne {
        private static ThreadLocal<Object> threadLocal = new ThreadLocal<Object>();
        private static Random random = new Random();
    
        public static class Task implements Runnable{
    
            @Override
            public void run() {
                // 在 Run 方法中,随机生成一个变量(线程要关联的数据),然后以当前线程名为 key 保存到 map 中
                Integer i =  random.nextInt();
                // 获取当前线程名
                String name = Thread.currentThread().getName();
    
                threadLocal.set(i);
                try {
                    Thread.sleep(30);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
    
                // 在 Run 方法结束之前,以当前线程名获取出数据并打印。查看是否可以取出操作
                
                Object o = threadLocal.get();
                System.out.println("线程["+name+"]快结束时取出关联的数据是"+o);
    
            }
        }
    
        public static void main(String[] args) {
            for (int i = 0; i <3 ; i++) {
                new Thread(new Task()).start();
            }
        }
    }

     

    使用 Filter 和 ThreadLocal 组合管理事务

    使用 ThreadLocal 来确保所有 dao 操作都在同一个 Connection 连接对象中完

    原理分析图:

     Filter 类代码:

    public class TransactionFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain
    filterChain) throws IOException, ServletException {
        try {
            filterChain.doFilter(servletRequest,servletResponse);
                JdbcUtils.commitAndClose();// 提交事务
            } catch (Exception e) {
                JdbcUtils.rollbackAndClose();//回滚事务
                e.printStackTrace();
            }
        }
    }    

    web.xml中的配置

    <filter>
    <filter-name>TransactionFilter</filter-name>
    <filter-class>com.atguigu.filter.TransactionFilter</filter-class>
    </filter>
    <filter-mapping>
    <filter-name>TransactionFilter</filter-name>
    <!-- /* 表示当前工程下所有请求 -->
    <url-pattern>/*</url-pattern>
    </filter-mapping> 

    一定要记得把 BaseServlet 中的异常往外抛给 Filter 过滤器

    public abstract class BaseServlet  extends HttpServlet {
    
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            doPost(req,resp);
        }
    
        @Override
        protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
            // 解决 post 请求中文乱码问题
            // 一定要在获取请求参数之前调用才有效
            req.setCharacterEncoding("UTF-8");
            String action = req.getParameter("action");
            try {
                // 获取 action 业务鉴别字符串,获取相应的业务 方法反射对象
                Method method = this.getClass().getDeclaredMethod(action,HttpServletRequest.class,HttpServletResponse.class);
                // 调用目标业务 方法
                method.invoke(this,req,resp);
            } catch (Exception e) {
                e.printStackTrace();
                throw new RuntimeException(e);//把异常抛给 Filter 过滤器
            }
    
        }
    }

    将所有异常都统一交给 Tomcat,让 Tomcat 展示友好的错误信息页面

     在 web.xml 中我们可以通过错误页面配置来进行管理。

        <!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
        <error-page>
            <!--error-code 是错误类型-->
            <error-code>500</error-code>
            <!--location 标签表示。要跳转去的页面路径-->
            <location>/pages/error/error500.jsp</location>
        </error-page>
    
        <!--error-page 标签配置,服务器出错之后,自动跳转的页面-->
        <error-page>
            <!--error-code 是错误类型-->
            <error-code>404</error-code>
            <!--location 标签表示。要跳转去的页面路径-->
            <location>/pages/error/error404.jsp</location>
        </error-page>

    .

  • 相关阅读:
    atom无法安装插件的解决方法之一
    css3伪类温故知新
    flex 布局笔记
    NPM 无法下载任何包的原因,解决方法
    flex align-content中的描述的“多根轴线的对齐方式”中的“多根轴线”到底是什么
    nodejs express 静态文件的路径
    当函数传入参数是引用类型的几种情况和现象。
    关于NODE NPM 输入命令后没反应的问题
    no input file specified
    获取form提交的返回值
  • 原文地址:https://www.cnblogs.com/zhaoyunlong/p/13901110.html
Copyright © 2011-2022 走看看