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)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了 ...
随机推荐
- VB.Net与C# 的语法比较
最近看代码或写代码时,经常把VB与C#的基本语法搞混,为方便查看,特对其异同进行对比: 變數初始化 VB.NET 自動將所有的變數初始化成 0 或 nothing.C# 在你未初始化變數之前不准你用該 ...
- LeetCode之链表
2. Add Two Numbers You are given two linked lists representing two non-negative numbers. The digits ...
- linux sudo 系统环境变量 用户环境变量
1. sudo就是普通用户临时拥有root的权限.好处在于,大多数时候使用用户自定义的配置,少数情况可以通过sudo实现root权限做事. 故而,需要注意的一点是,在你使用了sudo后,你临时不再是原 ...
- Git学习笔记——从一台电脑上传文件到Github上
目标:从一台电脑上传文件到Github上 前提: 1.这里假定已在Github上创建了仓库,建立了仓库 2.已在这台电脑上安装了Git客户端 实验环境: 1.Windows 10 64位,已安装了Gi ...
- 在Linux下访问Windows共享文件夹
说明 以下操作以Ubuntu为例,大家可以参考. 我在Ubuntu 14.04和16.04都试过了. Windows共享文件夹 如果局域网内有一台Windows主机,将指定文件夹设为共享,就可以在局域 ...
- AES加解密
AES加密类 <?php //php aes加密类 class AESMcrypt { public $iv = null; public $key = null; ; private $cip ...
- 如何使用vsphere client 克隆虚拟机
vSphere 是VMware公司推出一套服务器虚拟化解决方案. 工具/原料 vSphere 测试系统 方法/步骤 1.进入vSphere client,关闭需要克隆的虚拟机win7 2.选中ESXi ...
- [Training Video - 1] [Selenium Basics] [Download and Install Selenium]
Download Selenium Jars Configure jars in eclipse Webdriver http://docs.seleniumhq.org/download/ Sele ...
- java.sql.SQLException: Access denied for user ''@'localhost' (using password: YES)
这个问题是说明你的JDBC数据库连接位置出错了,请仔细检查 private static String url; private static String username; private sta ...
- Redis是可以安装成windows服务-开机自启 win7 64位
其实Redis是可以安装成windows服务的,开机自启动,命令如下: redis-server --service-install redis.windows.conf 安装完之后,就可看到Redi ...