首页 > 学院 > 开发设计 > 正文

java—ThreadLocal模式与OSIV模式(53)

2019-11-15 00:01:15
字体:
来源:转载
供稿:网友
java—ThreadLocal模式与OSIV模式(53)

ThreadLocal: 维护线程局部的变量。

ThreadLocal 不是线程。它就是一个Map。可以保存对象。

它保存的对象,只与当前线程相关。

当一个线程还没有运行完成时,如果不想传递数据,可以通过ThreadLocal来保存与这个Thread相关数据。

用ThreadLocal保存和获取数据的示例:

public class BaseDemo {    public static void main(String[] args) {        //声明Map<Object key,Object value>        //Object是值,key是当前线程的引用=Thread.currentThread();        ThreadLocal<Object> tl = new ThreadLocal<Object>();        //保存数据        tl.set("Helllo");        //获取数据        Object val = tl.get();        System.err.PRintln(val);    }}

当多个线程共同访问同一个资源时,用threadLocal来维护某个线程的变量:

一个应用项目中,一般只要有一个(static)threadlocal的实例就可以了:

public class MyThreadLocal {    //声明一个唯一的ThreadLocal    private static ThreadLocal<Object> tl = new ThreadLocal<Object>();     public static Object getObject(){        //先从tl中读取数据        Object o = tl.get();//  如果没有保存过,map.get(Thread.currentThread());        if(o==null){            //生成一个随机            o = new Random().nextInt(100);            //放到tl            tl.set(o);         }        return o;    }    public static void remove(){        tl.remove();     }}

对ThreadLocal内部保存的对象来说。你可以执行remove(无数)方法删除与当前thread相关的对象。也可以不执行:

因为:threadlocal内部使用的是弱引用:

WeakReferences

用ThreadLocal管理事务

用三层模式:

Serlvet(MVC-C) – Sevice(服务层) – dao(数据访问层)

写两个dao,在service中调用这两个dao。

让第一个dao成功。让第二个dao失败,必须都回滚。

第一步:开发两个dao

public class UserDao2 {    public void save(){        String sql = "insert into users values(?,?,?)";        QueryRunner run = new QueryRunner();        try {            run.update(DataSourceUtils.getConn(),sql,"U002","Jack","333");        } catch (SQLException e) {            throw new RuntimeException(e);        }            }}

第二步:开发Service

public class UserService {    //声明两个dao    private UserDao1 dao1 = new UserDao1();    private UserDao2 dao2 = new UserDao2();     public void save(){        dao1.save();        dao2.save();    }}

第三步:实现一个Servlet

public class UserServlet extends HttpServlet {    //声明service的实例    private UserService service = new UserService();    public void doGet(HttpServletRequest request, HttpServletResponse response)            throws ServletException, IOException {        service.save();    }}

第四步:修改datasourceutils.java

package cn.hx.utils;import java.sql.Connection;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class DataSourceUtils {    // 声明线程局部的容器    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();     private static DataSource ds;    static {        ds = // 默认的读取c3p0-config.xml中默认配置        new ComboPooledDataSource("itcast");    }    public static DataSource getDatasSource() {        return ds;    }    public static Connection getConn() {        // 先从tl这个容器中获取一次数据,如果当前线程已经保存过connection则直接返回这个connecton        Connection con = tl.get();         if (con == null) {            try {                con = ds.getConnection();// 每一次从ds中获取一个新的连接                //将这个con放到tl中                tl.set(con);             } catch (Exception e) {                e.printStackTrace();            }        }        return con;    }}

第五步:声明一个过虑器在过虑器开始事务

package cn.hx.filter;import java.io.IOException;import java.sql.Connection;import java.sql.SQLException;import javax.servlet.Filter;import javax.servlet.FilterChain;import javax.servlet.FilterConfig;import javax.servlet.ServletException;import javax.servlet.ServletRequest;import javax.servlet.ServletResponse;import cn.itcast.utils.DataSourceUtils;public class TxFilter implements Filter{    public void init(FilterConfig filterConfig) throws ServletException {    }    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain) throws IOException, ServletException {        //获取连接        Connection con = null;        //在try中开始事务        try{            con = DataSourceUtils.getConn();            //开始事务            con.setAutoCommit(false);            //放行            chain.doFilter(request, response);            //如果没有出错。            con.commit();        }catch(Exception e){            System.err.println("出错了");            try {                con.rollback();            } catch (SQLException e1) {                e1.printStackTrace();            }            throw new RuntimeException(e);        }finally{            try {                con.close();            } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public void destroy() {    }}

第六步:将过虑器配置到weeb.xml中。且对某个路径设置过虑

<filter>  <filter-name>tx</filter-name>  <filter-class>cn.itcast.filter.TxFilter</filter-class> </filter> <filter-mapping>  <filter-name>tx</filter-name>     <url-pattern>/tx/*</url-pattern>  </filter-mapping>

第七步:总结

在过虑器开始事务,就叫一种模式:OSIV模式》

OSIV – Open session In View =- 打开与数据库的会话在View层。- Hibernate.—AOP

第八步:优化:

在datasourceutls.java实现一个删除thredlocal中与线程相关的对象:

package cn.hx.utils;import java.sql.Connection;import javax.sql.DataSource;import com.mchange.v2.c3p0.ComboPooledDataSource;public class DataSourceUtils {    // 声明线程局部的容器    private static ThreadLocal<Connection> tl = new ThreadLocal<Connection>();    private static DataSource ds;    static {        ds = // 默认的读取c3p0-config.xml中默认配置        new ComboPooledDataSource("itcast");    }    public static DataSource getDatasSource() {        return ds;    }    public static Connection getConn() {        // 先从tl这个容器中获取一次数据,如果当前线程已经保存过connection则直接返回这个connecton        Connection con = tl.get();        if (con == null) {            try {                con = ds.getConnection();// 每一次从ds中获取一个新的连接                //将这个con放到tl中                tl.set(con);            } catch (Exception e) {                e.printStackTrace();            }        }        return con;    }    public static void remove(){        tl.remove();    } }
在TxFilter中调用一个remove:public class TxFilter implements Filter{    public void init(FilterConfig filterConfig) throws ServletException {    }    public void doFilter(ServletRequest request, ServletResponse response,            FilterChain chain) throws IOException, ServletException {        System.err.println("thread:"+Thread.currentThread().getName());        //获取连接        Connection con = null;        //在try中开始事务        try{            con = DataSourceUtils.getConn();            //开始事务            con.setAutoCommit(false);            //放行            chain.doFilter(request, response);            //如果没有出错。            con.commit();        }catch(Exception e){            System.err.println("出错了");            try {                if(e instanceof SQLException){                    con.rollback();                }else{                    con.commit();                }            } catch (SQLException e1) {                e1.printStackTrace();            }            throw new RuntimeException(e);        }finally{            try {                con.close();                DataSourceUtils.remove();             } catch (SQLException e) {                // TODO Auto-generated catch block                e.printStackTrace();            }        }    }    public void destroy() {    }}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表