博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java connection 共享_【java項目實戰】ThreadLocal封裝Connection,實現同一線程共享資源...
阅读量:6505 次
发布时间:2019-06-24

本文共 4560 字,大约阅读时间需要 15 分钟。

線程安全一直是程序員們關注的焦點。多線程也一直是比較讓人頭疼的話題,想必大家以前也遇到過各種各種的問題。我就不再累述了。當然,解決方案也有非常多,這篇博文給大家提供一種非常好的解決線程安全問題的思路。

首先。我們先簡單的認識一下ThreadLocal,之后是實例+解析,最后一句話總結。

1、認識一下ThreaLocal

認識ThreadLocal必需要通過api文檔,不只具有說服力,並且它會給你更加全面的解釋。以下我我給大家從api文檔上截取一張圖,並標出來了七點需要重點理解的內容,實例過后的解析也是重點解釋這七部分。

800a0ab2beee4c11fede677ecb5dc90b.jpe

對於上面的內容。不理解沒有關系,我們通過以下的實例加深一下理解,實例之后我會給大家一個更加深入的解釋。

2、ThreaLocal封裝Connection實例+解析

以下的代碼僅僅是ThreaLocal封裝Connection的核心代碼,對於多余的內容成功避開就好,而且有一部分代碼是“dom4j解析xml文件。連接數據庫”的內容,很適合剛開始學習的人,如有須要,請您移駕到此。

package com.bjpowernode.drp.util;

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.SQLException;

import java.sql.Statement;

/**

* 採用ThreadLocal封裝Connection

* 僅僅要線程是活動的,沒有結束,ThreadLocal是可訪問的,就能夠訪問本線程的connection

*

* @author liang

*

*/

public class ConnectionManager {

//使用ThreadLocal保存Connection變量

private static ThreadLocal connectionHolder = new ThreadLocal();

/**

* 連接Connection

* @return

*/

public static Connection getConnection(){

//ThreadLocal取得當前線程的connection

Connection conn = connectionHolder.get();

//假設ThreadLocal沒有綁定對應的Connection。創建一個新的Connection,

//並將其保存到本地線程變量中。

if(conn == null){

try {

JdbcConfig jdbcConfig = XmlConfigReader.getInstance().getJdbcConfig();

Class.forName(jdbcConfig.getDriverName());

conn = DriverManager.getConnection(jdbcConfig.getUrl(), jdbcConfig.getUserName(), jdbcConfig.getPassword());

//將當前線程的Connection設置到ThreadLocal

connectionHolder.set(conn);

} catch (ClassNotFoundException e) {

e.printStackTrace();

throw new ApplicationException("系統錯誤,請聯系系統管理員");

} catch (SQLException e) {

e.printStackTrace();

throw new ApplicationException("系統錯誤。請聯系系統管理員");

}

}

return conn;

}

/**

* 關閉Connection,清除集合中的Connection

*/

public static void closeConnection(){

//ThreadLocal取得當前線程的connection

Connection conn = connectionHolder.get();

//當前線程的connection不為空時。關閉connection.

if(conn != null){

try{

conn.close();

//connection關閉之后,要從ThreadLocal的集合中清除Connection

connectionHolder.remove();

}catch(SQLException e){

e.printStackTrace();

}

}

}

以下的代碼給大家演示了:ThreadLocal怎樣在同一個線程中能夠共享Connection資源。

package com.bjpowernode.drp.flowcard.manager.impl;

import java.sql.Connection;

import java.util.Date;

import com.bjpowernode.drp.flowcard.dao.FlowCardDao;

import com.bjpowernode.drp.flowcard.domain.FlowCard;

import com.bjpowernode.drp.flowcard.manager.FlowCardManager;

import com.bjpowernode.drp.util.ApplicationException;

import com.bjpowernode.drp.util.BeanFactory;

import com.bjpowernode.drp.util.ConnectionManager;

import com.bjpowernode.drp.util.DaoException;

import com.bjpowernode.drp.util.PageModel;

public class FlowCardManagerImpl implements FlowCardManager {

private FlowCardDao flowCardDao;

//構造函數

public FlowCardManagerImpl(){

this.flowCardDao = (FlowCardDao) BeanFactory.getInstance().getDaoObject(FlowCardDao.class);

}

@Override

public void addFlowCard(FlowCard flowCard) throws ApplicationException {

Connection conn = null;

try{

//從ThreadLocal中獲取線程相應的Connection

conn = ConnectionManager.getConnection();

//開始事務

ConnectionManager.beginTransaction(conn);

//生成流向單單號

String flowCardVouNo = flowCardDao.generateVouNo();

//加入流向單主信息

flowCardDao.addFlowCardMaster(flowCardVouNo, flowCard);

//加入流向單明細信息

flowCardDao.addFlowCardDetail(flowCardVouNo, flowCard.getFlowCardDetailList());

//提交事務

ConnectionManager.commitTransaction(conn);

}catch(DaoException e){

//回滾事務

ConnectionManager.rollbackTransaction(conn);

throw new ApplicationException("加入流向單失敗!

");

}finally{

//關閉Connection並從ThreadLocal集合中清除

ConnectionManager.closeConnection();

}

}

}

解析:

1、該類提供了線程局部變量。它獨立於變量的初始化副本

大家可能對局部變量不太理解,為什么不是成員變量或全局變量,此時就涉及到變量的作用域問題。

ThreadLocal具有比局部變量更大一點的作用域,在此作用域內資源能夠共享,線程是安全的。

我們還了解到ThreadLocal並不是本地線程,而是一個線程變量,它僅僅是用來維護本地變量。

針對每一個線程提供自己的變量版本號,避免了多線程的沖突問題,每一個線程僅僅須要維護自己的版本號就好,彼此獨立,不會影響到對方。

2、每一個線程有自己的一個ThreadLocal。改動它並不影響其它線程

我們依據以下這張圖能夠看到,向ThreadLocal里面存東西就是創建了一個Map,一個線程相應一個Map集合,然后ThreadLocal把這個Map掛到當前的線程底下。一個key值相應一個value,這樣Map就僅僅屬於當前線程。(假設您不理解Map的特點能夠猛戳)

098c6333e28c5a77f5c7641d04155206.png

3、在線程消失之后。其線程局部實例的全部副本都會被垃圾回收(除非存在對這些副本的其它引用)。

上面我們知道了變量副本的存放在了map中。當我們不在調用set,此時不在將引用指向該‘map’。而本線程退出時會運行資源回收操作。將申請的資源進行回收。事實上就是將引用設置為null。

這時已經不在有不論什么引用指向該map,故而會被垃圾回收。

3、對照ThreadLocal和synchronized同步機制

同樣點:

1、ThreadLocal和線程同步機制都能解決多線程中同樣變量的訪問沖突問題。

不同點:

1、適用的情況不同

在同步機制中,使用同步保證同一時間僅僅有一個線程訪問,不能同一時候訪問共享資源,否則就是出現錯誤。ThreadLocal則隔離了相關的資源,並在同一個線程中能夠共享這個資源。

彼此獨立,改動不會影響到對方。

2、終於實現的效果不同

對於多線程資源共享問題。同步機制採用了“以時間換空間”的方式,而ThreadLocal採用了“以空間換時間”的方式。前者僅提供一份變量。讓不同的線程排隊訪問。而后者為每個線程都提供了一份變量。因此能夠同一時候訪問而互不影響。

上面博客的鏈接相同也是線程同步機制synchronized的實例。大家能夠通過兩個實例體會一下它們的異同點,再加上異同點解析。相信您對它們已經有了非常深刻的認識。

4、一句話總結ThreadLocal

ThreadLocal是解決線程安全問題一個非常好的思路。在非常多情況下。ThreadLocal比直接使用synchronized同步機制解決線程安全問題更簡單,更方便。而且程序擁有更高的並發性。

转载地址:http://fqgyo.baihongyu.com/

你可能感兴趣的文章
Eclipse中绑定java源代码
查看>>
Gena's Code
查看>>
正则式的使用
查看>>
7.Knockout.Js(Mapping插件)
查看>>
jqgride实现每一行的单选
查看>>
CGAL4.10 / CGAL4.13编译
查看>>
机器学习数学基础知识备忘
查看>>
HDFS开发中的一些问题(逐步补充)
查看>>
虚基类&虚继承
查看>>
SRM 670 div2 A B C div1 A(贪心,子问题合并)
查看>>
css 一些常用属性总结
查看>>
泛在电力物联网有项核心技术 你听过没有?
查看>>
构造函数
查看>>
webapi支持跨域访问
查看>>
如何学习FPGA
查看>>
IPS简单使用方法
查看>>
第八次作业
查看>>
[转载] Discrete Mathematics——02 命题逻辑等价与联接词完备
查看>>
核心动画——弹簧动画二
查看>>
db2 基础语法
查看>>