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();
//放到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","");
} 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() {
}
}

java—ThreadLocal模式与OSIV模式(53)的更多相关文章

  1. Java设计模式之工厂方法模式(转) 实现是抽象工厂?

    Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织   2009-02-25   来源:IT168网站   文本Tag: 设计模式 Java [IT168 技术文章]         ...

  2. Java中生产者与消费者模式

    生产者消费者模式 首先来了解什么是生产者消费者模式.该模式也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了两个共享固定大小缓冲区的线 ...

  3. Java 原型模式(克隆模式)

      Java 的设计模式有 23 种,前段时间小编已经介绍了单例模式,由于我们在学习 Spring 的时候在 bean 标签的学习中碰到了今天要讲的原型模式,那么小编就已本文来介绍下原型模式. 原型模 ...

  4. Java设计模式之行为型模式

    行为型模式共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 策略模式:策略模式的决定权在用户,系统本身提供不同 ...

  5. Java设计模式之创建型模式

    创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类

  6. java中的23中设计模式(转)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

  7. Java设计模式5:原型模式

    原型模式 原型模式属于对象的创建模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意. 原型模式结构 原型模式要求对象实现一个 ...

  8. Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别

    前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...

  9. java中的23中设计模式(转载的,有时间一定要熟读)

    设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...

随机推荐

  1. MyEclipse8.6启动后提示内存不足的解决方案(亲测,完美解决)

    转自:http://www.bubuko.com/infodetail-1625857.html 最近可能由于公司项目大了,启动MyEclipse后经常提示内存不足的警告框,如下: 其实点击close ...

  2. JS调用webservice的两种方式

    协议肯定是使用http协议,因为soap协议本身也是基于http协议.期中第二种方式:只有webservice3.5以后版本才可以成功 第一种方式:构造soap格式的body,注意加粗的黄色标识,比如 ...

  3. S 合伙人

    [Public] ConnectString=host="siebel://10.10.0.46:2321/HC_CRM/SMObjMgr_chs ConnectUserName=SADMI ...

  4. 《GB/T 20988-2007:信息系统灾难恢复规范》[中](国家质检总局 & 国标委)阅读笔记

    第 0 章:引言 [感]GB/T 20988 引用了 SHARE 78 会议(标准)上的有关内容和思想,并结合国家重要信息系统行业技术发展和实践经验制定而成. GB/T 20988 提出了信息系统灾难 ...

  5. iconv-go升级过程中的编译问题

    工作项目原因,需要对golang进行升级.升级之后老的iconv-go运行有问题.因为新的golang运行更加严格,所以需要升级iconv-go. 从djimenez/iconv-go 拉下来代码进行 ...

  6. springMVC框架介绍以及运行流程(图解)

    1 Springmvc是什么? spring web mvc和struts2都属于表现层的框架,spring web mvc是spring框架的一部分(所以spring mvc与spring之间不需要 ...

  7. qt4代码到qt5代码出错

    1.error C2039: “toAscii”: 不是“QString”的成员 QT5.0.1把这个函数取消掉了,可以用toLatin1这个函数

  8. git和码云的使用

    什么是码云 快速入门 Git入门 码云是开源中国社区2013年推出的基于 Git 的完全免费的代码托管服务,这个服务是基于 Gitlab 开源软件所开发的,我们在 Gitlab 的基础上做了大量的改进 ...

  9. mvc api odata查询选项之 $inlinecount $format 选项(转)

    出处:http://www.it165.net/pro/html/201505/40236.html 网上百度“odata 语法”会出来很多结果,其中有一项是比较一致的,那就是odata支持一下几种语 ...

  10. parseInt(string, radix)

    参数 描述 string 必需.要被解析的字符串. radix 可选.表示要解析的数字的基数.该值介于 2 ~ 36 之间. 如果省略该参数或其值为 0,则数字将以 10 为基础来解析.如果它以 “0 ...