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();
//放到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)的更多相关文章
- Java设计模式之工厂方法模式(转) 实现是抽象工厂?
Java设计模式之工厂方法模式 责任编辑:覃里作者:Java研究组织 2009-02-25 来源:IT168网站 文本Tag: 设计模式 Java [IT168 技术文章] ...
- Java中生产者与消费者模式
生产者消费者模式 首先来了解什么是生产者消费者模式.该模式也称有限缓冲问题(英语:Bounded-buffer problem),是一个多线程同步问题的经典案例.该问题描述了两个共享固定大小缓冲区的线 ...
- Java 原型模式(克隆模式)
Java 的设计模式有 23 种,前段时间小编已经介绍了单例模式,由于我们在学习 Spring 的时候在 bean 标签的学习中碰到了今天要讲的原型模式,那么小编就已本文来介绍下原型模式. 原型模 ...
- Java设计模式之行为型模式
行为型模式共11种:策略模式.模板方法模式.观察者模式.迭代子模式.责任链模式.命令模式.备忘录模式.状态模式.访问者模式.中介者模式.解释器模式. 策略模式:策略模式的决定权在用户,系统本身提供不同 ...
- Java设计模式之创建型模式
创建型模式分为五类:工厂方法模式.抽象工厂模式.单例模式.建造者模式.原型模式 一.工厂方法模式:接口-实现类.工厂类
- java中的23中设计模式(转)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
- Java设计模式5:原型模式
原型模式 原型模式属于对象的创建模式,通过给出一个原型对象来指明所有创建的对象的类型,然后用复制这个原型对象的办法创建出更多同类型的对象,这就是原型模式的用意. 原型模式结构 原型模式要求对象实现一个 ...
- Java虚拟机6:内存溢出和内存泄露、并行和并发、Minor GC和Full GC、Client模式和Server模式的区别
前言 之前的文章尤其是讲解GC的时候提到了很多的概念,比如内存溢出和内存泄露.并行与并发.Client模式和Server模式.Minor GC和Full GC,本文详细讲解下这些概念的区别. 内存溢出 ...
- java中的23中设计模式(转载的,有时间一定要熟读)
设计模式(Design Patterns) --可复用面向对象软件的基础 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
随机推荐
- DB2 日期时间函数
db2日期时间函数 (DATE(TRIM(CHAR(DT#11Y))||'-'||TRIM(CHAR(DT#11M))||'-'||TRIM(CHAR(DT#11D))) BETWEEN DATE(' ...
- 如何让自己的exe程序开机自启动
方法一. ①鼠标右键自己的exe程序,创建快捷方式 ②win+R,打开运行对话框,输入shell:startup,如下图: 将exe文件的的快捷方式拷贝到这个目录下,然后下次重启的时候自己的应用程序就 ...
- Git----远程仓库01
到目前为止,我们已经掌握了如何在Git仓库里对一个文件进行时光穿梭,你再也不用担心文件备份或者丢失的问题了 可是用过集中式版本控制系统SVN的童鞋们会站出来说,这些功能在SVN里早就有了,没看出Git ...
- 第三方工具Jdom解析XML
需要导入的jar包:jdom-2.0.6.jar package com.huawei.xml; import java.io.File;import java.io.FileOutputStream ...
- docker 网络配置路由转发
建好flannel 网络之后 iptables -L -n 查看 要全是accept iptables -P FORWARD ACCEPT 开启路由转发 修改/etc/sysctl.conf文件,添加 ...
- 使用javascript,jquery实现的图片轮播功能
使用javascript,jquery实现的图片轮播功能本功能采用最基础的javascript和一些简单的jquery技术实现,易理解,以修改使用,代码简易,适合刚开始接触到网站开发的朋友们参考.可以 ...
- Mybatis框架的输出映射类型
Mapper.xml映射文件中定义了操作数据库的sql,每个sql是一个statement,映射文件是mybatis的核心. resultType(输出类型) 1.输出简单类型 (1)我们在UserM ...
- MySQL之——GROUP BY分组取字段最大值
转载自:http://blog.csdn.net/l1028386804/article/details/54657412 假设有一个业务场景,需要查询用户登录记录信息,其中表结构如下: CREATE ...
- EventBus事件总线框架(发布者/订阅者模式,观察者模式)
一. android应用内消息传递的方式: 1. handler方式-----------------不同线程间传递消息. 2. Interface接口回调方式-------任意两个对象. 3. In ...
- spring获取webapplicationcontext,applicationcontext几种方法详解(转载)
转载自 http://www.blogjava.net/Todd/archive/2010/04/22/295112.html 方法一:在初始化时保存ApplicationContext对象 代码: ...