`

ThreadLocal 我所用到的地方

阅读更多

92.  现在来看怎么把三个方法保证同步,servlet是单实例多线程运行的,你去调用FlowCardServlet就
会启动一个线程,在这个线程里其实就调用了你写的那三个方法,现在我就只要保证你这三个方法都在一个线程里面就可以了。

93.  在同一个线程里保证使用一个connection这就涉及到一个类ThreadLocal
这个类不是本地线程的意思,这个类就在java.lang包中。作用:你放在这里面的东西,他会在整个线程里共享,在其它线程里不共享。


94.  不用框架要考虑的东西太多了,这样就会造成以后的维护成本提高啊。


95.  你可以这样理解,这个类的底层是 一个map{
key=当前线程变量001,也可以理解为这个是一个唯一标识的东西吧,不好理解,你就这么理解
value = new connection()

key=当前线程变量002
value = new connection()  这两个connection是不一样的,他们是不相互干扰的。
}

在这整个线程中就共享着一个
value对应的就是你具体的东西,你爱放什么就放什么,他接收一个Object参数。


96.  ThreadLocal这个很重要,因为现在很多都使用这个东西。
这个类里面就四个方法。
public void set(T value){}你传一个connection进来,他就放到了一个map里面去了。

public void set(T value){
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if(map != null)
    map.set(this,value);
else
    createMap(t,value);
}别人再调用,他又map.set()设置一个了。如果有10个人设置进去东西了,我怎么就能拿到我的呢?


97.  他还有一个get(T value)方法。
map.get(0001);你当前线程对应的是0001  他就拿0001的东西。


98.  现在再建一个类来封装ThreadLocal
他命名命得好啊,connection的管理
public class ConnectionManager{
private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();

现在都是在多线程中运行的,你开一个就开一个线程我得看看,在当前线程中绑没绑定一个connection
public static Connection getConnection(){
Connection conn = connectionHolder.get();
用了泛型你不用管了,里面就是coneciton
if(conn == null){ 当前线程没有绑定我就创建
JdbcInfo jdbcInfo = ConfigReader.getInstance().getJdbcInfo();
Class.forName(jdbcInfo.getDriverName());
conn = DriverManager.getConneciton(jdbcInfo.getUrl(),jdbcInfo.getUsername(),jdbcInfo.getPassword());
connectionHolder.set(conn);
}
}
return conn;
}

holder:持有

关闭方法,你想你要关闭,你怎么关,你只能关你自己的connection
public static void closeConnection(){
Connection conn = connectionHolder.get();
if(conn !=null){
    conn.close();
conntionHolder.remove();你把他关了,他map里面的东西还存在啊,所以你得移除了。
}
}


99.  这思想就和我在方法中定义的变量只能在这个方法里面使用。


100.  我们还可以采用同步机制来解决线程安全问题

 

 

1.  connection什么时候关闭,应该是那三个方法全部执行完


2.  这个connection应该是在FlowCardServiceImpl这一层开,在这一层关。

 

 

 

/**
 * 采用ThreadLocal封装Connection
 * ThreadLocal可以在同一个线程中共享变量
 * @author Administrator
 *
 */
public class ConnectionManager {

    private static ThreadLocal<Connection> connectionHolder = new ThreadLocal<Connection>();
   
    /**
     * 取得connection
     * @return
     */
    public static Connection getConnection() {
        Connection conn = connectionHolder.get();
        //如果在ThreadLocal中不存在与当前线程绑定的Connection
        //那么我们就创建一个Connection,并将其放到ThreadLocal中
        if (conn == null) {
            try {
                //取得jdbc配置信息
                JdbcInfo jdbcInfo = ConfigReader.getInstance().getJdbcInfo();
                Class.forName(jdbcInfo.getDriverName());
                conn = DriverManager.getConnection(jdbcInfo.getUrl(), jdbcInfo.getUsername(), jdbcInfo.getPassword());
               
                //放到ThreadLocal中
                connectionHolder.set(conn);
            } catch (ClassNotFoundException e) {
                //记录日志可以将类不能找记录进去,这样可以更准确的定位问题
                //但是给用户不应该抛出类不能找到,应该抛出用户能够理解的错误
                e.printStackTrace();
                throw new AppException("系统出现故障,请联系系统管理员!");
            } catch (SQLException e) {
                e.printStackTrace();
                throw new AppException("系统出现故障,请联系系统管理员!");
            }
        }
        return conn;
    }
   
    /**
     * 关于connection
     */
    public static void closeConnection() {
        Connection conn = connectionHolder.get();
        if (conn != null) {
            try {
                conn.close();
                //从ThreadLocal中移除
                connectionHolder.remove();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
       
    }
   
    public static void close(PreparedStatement pstmt) {
        if (pstmt != null) {
            try {
                pstmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void close(ResultSet rs) {
        if (rs != null) {
            try {
                rs.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void commit(Connection conn) {
        if (conn != null) {
            try {
                conn.commit();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void rollback(Connection conn) {
        if (conn != null) {
            try {
                conn.rollback();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void setAutoCommit(Connection conn, boolean autoCommit) {
        if (conn != null) {
            try {
                conn.setAutoCommit(autoCommit);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
   
    public static void close(Statement stmt) {
        if (stmt != null) {
            try {
                stmt.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }   
}

分享到:
评论

相关推荐

    ThreadLocal应用示例及理解

    **线程局部变量(ThreadLocal)是Java编程中一个非常重要的工具类,它在多线程环境下提供了线程安全的数据存储。ThreadLocal并不是一个变量,而是一个类,它为每个线程都创建了一个独立的变量副本,使得每个线程都...

    ThreadLocal

    ThreadLocal是Java编程语言中的一个类,用于在多线程环境中提供线程局部变量。它是一种特殊类型的变量,每个线程都有自己的副本,互不影响,从而实现线程间数据隔离。ThreadLocal通常被用来解决线程共享数据时可能...

    从ThreadLocal的使用到Spring的事务管理

    例如,在Web应用服务器中,我们可以用ThreadLocal存储用户的会话信息,确保每个请求都访问到自己专属的数据。 ThreadLocal的使用通常包括以下步骤: 1. 创建ThreadLocal实例,声明变量类型。 2. 在需要的地方,通过...

    理解ThreadLocal

    理解ThreadLocal 理解ThreadLocal 理解ThreadLocal 理解ThreadLocal

    ThreadLocal 内存泄露的实例分析1

    在 `LeakingServlet` 的 `doGet` 方法中,如果 `ThreadLocal` 没有设置值,那么会创建一个新的 `MyCounter` 并设置到 `ThreadLocal` 中。关键在于,一旦 `MyCounter` 被设置到 `ThreadLocal`,那么它将与当前线程...

    java 简单的ThreadLocal示例

    在需要的地方,你可以通过`set()`方法为当前线程的ThreadLocal副本设置值。 ```java threadLocal.set("这是线程A的值"); ``` 3. **获取线程局部变量的值:** 当你需要访问这个值时,使用`get()`方法。这将返回与...

    ThreadLocal整理.docx

    ThreadLocal 整理 ThreadLocal 是 Java 中的一个重要组件,它能够在每个线程中保持独立的副本。这个功能是通过 Thread 类中的 threadLocals 属性来实现的,这个属性实际上是一个 Entry 数组,其中的每个 Entry 都...

    java事务 - threadlocal

    可以在不同的线程中维护各自的事务状态,比如在Spring框架中,每个线程的ThreadLocal可以存储一个TransactionStatus对象,这样就可以在线程内部管理当前事务的状态,而不会影响到其他线程。这种方式在高并发的微服务...

    threadLocal

    ThreadLocal的使用方法通常是创建一个ThreadLocal实例,然后在需要的地方通过它的`set()`方法设置线程局部变量的值,通过`get()`方法获取该变量的副本。在生命周期结束后,通常需要调用`remove()`方法清除线程的副本...

    ThreadLocal简单Demo

    **线程局部变量(ThreadLocal)** 在Java编程中,`ThreadLocal`是...以上就是关于`ThreadLocal`及其内部类`ThreadLocalMap`的基础知识,它们在多线程编程中起到关键作用,帮助开发者实现高效、安全的线程局部变量管理。

    正确理解ThreadLocal.pdf

    ### 正确理解ThreadLocal:深入解析其工作原理与应用场景 #### 一、ThreadLocal的基本概念 `ThreadLocal`是Java平台提供的一种线程局部变量的解决方案,它为每一个使用该变量的线程都提供了独立的变量副本,使得每...

    java中ThreadLocal详解

    接着,将`ThreadLocal`对象作为键,对应的值作为值,存储到`ThreadLocalMap`中。 #### 四、ThreadLocal的内存泄漏问题及其解决方案 尽管使用弱引用来避免内存泄漏,但在某些情况下,仍然可能引起内存泄漏。例如,...

    ThreadLocal的几种误区

    在服务器端,线程池的存在可能导致多个用户的请求被分配到同一个线程处理,因此,如果不注意清理,ThreadLocal变量可能会被不同用户访问到,造成数据泄露。 误区三:每个用户访问会有新的ThreadLocal 理论上来讲,...

    ThreadLocal_ThreadLocal源码分析_

    4. **注意线程池中的ThreadLocal**:线程池中的线程可能会被重用,若不清理ThreadLocal,可能导致后续任务访问到错误的变量副本。 通过理解ThreadLocal的原理和最佳实践,我们可以更有效地利用它来解决多线程环境下...

    ThreadLocal详解.md

    学习ThreadLocal,了解其中的原理,以及学习其中的优点!避免坑点!!

    设计模式及ThreadLocal资料

    本资料主要聚焦于两种设计模式以及Java中的ThreadLocal特性。 首先,我们来探讨单例模式。单例模式是一种确保一个类只有一个实例,并提供全局访问点的设计模式。在Java中,通常通过私有构造函数、静态工厂方法或...

    Quartz-ThreadLocal.rar

    3. **状态传递**:在 Quartz 作业的执行过程中,ThreadLocal 可以用来在不同阶段传递状态,比如在 Job 的 execute 方法中设置状态,然后在其他地方读取。 学习这个压缩包中的内容,可以帮助你理解如何在实际项目中...

Global site tag (gtag.js) - Google Analytics