V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
gao6rich
V2EX  ›  Java

ThreadLocal

  •  
  •   gao6rich · 2022-12-12 17:29:28 +08:00 · 2589 次点击
    这是一个创建于 735 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问 Java 中为什么一个数据库的 Connection 放到 ThreadLocal 里面复制出来多个副本在多线程中使用的话,可以互相不影响的用,实际上跟数据库不是还是只有一个连接吗?如果多线程不是同一个连接的话,跟不使用 ThreadLocal ,每个线程新建一个 connection 有什么区别呢[发呆]

    13 条回复    2022-12-14 10:09:36 +08:00
    7911364440
        1
    7911364440  
       2022-12-12 17:32:21 +08:00
    贴下代码?
    ajaxgoldfish
        2
    ajaxgoldfish  
       2022-12-12 17:35:57 +08:00
    个人看法,主要用于传值,比如 Controler 层处理过后还需要给 mapper 层这种情景
    optional
        3
    optional  
       2022-12-12 17:47:56 +08:00 via iPhone
    这样连接数不就和线程数量绑定了,对于连接数有限的数据库实例不是很尴尬,比如 pg
    chendy
        4
    chendy  
       2022-12-12 17:50:43 +08:00
    一个线程一个连接
    做声明式的事务控制之类的比较方便
    wolfie
        5
    wolfie  
       2022-12-12 18:19:34 +08:00
    看得一堆问号。

    去看看数据库连接池。
    gao6rich
        6
    gao6rich  
    OP
       2022-12-12 19:17:59 +08:00
    class ConnectionManager {
    private Connection connect = null;

    public Connection openConnection() {
    if (connect == null) {
    connect = DriverManager.getConnection();
    }
    return connect;
    }

    public void closeConnection() {
    if (connect != null)
    connect.close();
    }
    }

    class Dao {
    public void insert() {
    ConnectionManager connectionManager = new ConnectionManager();
    Connection connection = connectionManager.openConnection();

    // 使用 connection 进行操作

    connectionManager.closeConnection();
    }
    }
    ===========================================使用 ThreadLocal

    public class ConnectionManager {

    private static final ThreadLocal<Connection> dbConnectionLocal = new ThreadLocal<Connection>() {
    @Override
    protected Connection initialValue() {
    try {
    return DriverManager.getConnection("", "", "");
    } catch (SQLException e) {
    e.printStackTrace();
    }
    return null;
    }
    };

    public Connection getConnection() {
    return dbConnectionLocal.get();
    }
    }
    ===========================================不使用 ThreadLocal

    这两者有什么区别呢
    franpinx2
        7
    franpinx2  
       2022-12-12 19:35:35 +08:00
    你这样没什么区别 主要看 DriverManager.getConnection()这个方法是怎么实现的
    franpinx2
        8
    franpinx2  
       2022-12-12 19:40:18 +08:00
    @gao6rich 看了下 这个方法的底层没有做池化 所以你每次都会建立一个新的数据库连接 是个不推荐的写法
    kaneg
        9
    kaneg  
       2022-12-12 19:51:29 +08:00
    数据库的连接可是很宝贵的资源,而线程池里的线程尽管不是毫无价值,但比起数据库的连接来说便宜很多。所以,当某个线程需要数据库连接的时候,就从连接池中拿一个,用完立即释放以便别的线程可以申请到。
    boatrain1111
        10
    boatrain1111  
       2022-12-12 19:54:19 +08:00
    用的是同一个 tcp 连接吧
    CRVV
        11
    CRVV  
       2022-12-12 23:29:12 +08:00
    thread-local 是指每个线程都有自己的变量。虽然代码里面是同一个变量,但每个线程用的是各自的变量。
    所以每个线程里面用的是不同的 connection 。数据库连接和线程数一样多。


    > 如果多线程不是同一个连接的话,跟不使用 ThreadLocal ,每个线程新建一个 connection 有什么区别呢

    如果每个线程新建一个连接,用完就关下次再重连,那就没有区别。
    如果要把连接留着以后再用,就需要一个地方存着这个 connection ,下次再用的时候每个线程每次都能拿到当前线程的 connection 。当然可以自己实现这一套东西,实现好了你就重写了 thread-local
    lyusantu
        12
    lyusantu  
       2022-12-13 09:26:37 +08:00
    ThreadLocal 允许线程之间共享数据库连接
    byte10
        13
    byte10  
       2022-12-14 10:09:36 +08:00
    17 楼 表达正确,ThreadLocal 主要是就是传递开启事务中的 mysql 链接。同一个事务,连接是同一个的。如果没有事务的话,你同一个线程得到的 mysql 连接都可能不一样。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5434 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 01:45 · PVG 09:45 · LAX 17:45 · JFK 20:45
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.