<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    CONAN ZONE

    你越掙扎我就越興奮

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      0 Posts :: 282 Stories :: 0 Comments :: 0 Trackbacks

    EasyDBO的數(shù)據(jù)庫(kù)連接部分,為了給每個(gè)連接提供上下文,程序用到了一個(gè)關(guān)鍵的類(lèi)——ThreadLocal。

    什么是ThreadLocal?

    顧名思義它是local variable(線(xiàn)程局部變量)。它的功用非常簡(jiǎn)單,就是為每一個(gè)使用該變量的線(xiàn)程都提供一個(gè)變量值的副本,是每一個(gè)線(xiàn)程都可以獨(dú)立地改變自己的副本,而不會(huì)和其它線(xiàn)程的副本沖突。從線(xiàn)程的角度看,就好像每一個(gè)線(xiàn)程都完全擁有該變量。

    使用場(chǎng)景

    1. To keep state with a thread (user-id, transaction-id, logging-id)
    2. To cache objects which you need frequently

    ThreadLocal類(lèi)

    它主要由四個(gè)方法組成initialValue(),get(),set(T),remove(),其中值得注意的是initialValue(),該方法是一個(gè)protected的方法,顯然是為了子類(lèi)重寫(xiě)而特意實(shí)現(xiàn)的。該方法返回當(dāng)前線(xiàn)程在該線(xiàn)程局部變量的初始值,這個(gè)方法是一個(gè)延遲調(diào)用方法,在一個(gè)線(xiàn)程第1次調(diào)用get()或者set(Object)時(shí)才執(zhí)行,并且僅執(zhí)行1次。ThreadLocal中的確實(shí)實(shí)現(xiàn)直接返回一個(gè)null:

    ThreadLocal的原理

    ThreadLocal是如何做到為每一個(gè)線(xiàn)程維護(hù)變量的副本的呢?其實(shí)實(shí)現(xiàn)的思路很簡(jiǎn)單,在ThreadLocal類(lèi)中有一個(gè)Map,用于存儲(chǔ)每一個(gè)線(xiàn)程的變量的副本。比如下面的示例實(shí)現(xiàn):

    public class ThreadLocal
    {
    private Map values = Collections.synchronizedMap(new HashMap());
    public Object get()
    {
    Thread curThread = Thread.currentThread();
    Object o = values.get(curThread);
    if (o == null && !values.containsKey(curThread))
    {
    o = initialValue();
    values.put(curThread, o);
    }
    return o;
    }

     public void set(Object newValue)
    {
    values.put(Thread.currentThread(), newValue);
    }

     public Object initialValue()
    {
    return null;
    }
    }

    ThreadLocal 的使用

    使用方法一:

    Hibernate的文檔時(shí)看到了關(guān)于使ThreadLocal管理多線(xiàn)程訪(fǎng)問(wèn)的部分。具體代碼如下

    1.  public static final ThreadLocal session = new ThreadLocal();
    2.  public static Session currentSession() {
    3.      Session s = (Session)session.get();
    4.      //open a new session,if this session has none
    5.   if(s == null){
    6.      s = sessionFactory.openSession();
    7.      session.set(s);
    8.   }
          return s;
    9. }

    我們逐行分析
    1。 初始化一個(gè)ThreadLocal對(duì)象,ThreadLocal有三個(gè)成員方法 get()、set()、initialvalue()。
        如果不初始化initialvalue,則initialvalue返回null。
    3。session的get根據(jù)當(dāng)前線(xiàn)程返回其對(duì)應(yīng)的線(xiàn)程內(nèi)部變量,也就是我們需要的net.sf.hibernate.Session(相當(dāng)于對(duì)應(yīng)每個(gè)數(shù)據(jù)庫(kù)連接).多線(xiàn)程情況下共享數(shù)據(jù)庫(kù)鏈接是不安全的。ThreadLocal保證了每個(gè)線(xiàn)程都有自己的s(數(shù)據(jù)庫(kù)連接)。
    5。如果是該線(xiàn)程初次訪(fǎng)問(wèn),自然,s(數(shù)據(jù)庫(kù)連接)會(huì)是null,接著創(chuàng)建一個(gè)Session,具體就是行6。
    6。創(chuàng)建一個(gè)數(shù)據(jù)庫(kù)連接實(shí)例 s
    7。保存該數(shù)據(jù)庫(kù)連接s到ThreadLocal中。
    8。如果當(dāng)前線(xiàn)程已經(jīng)訪(fǎng)問(wèn)過(guò)數(shù)據(jù)庫(kù)了,則從session中g(shù)et()就可以獲取該線(xiàn)程上次獲取過(guò)的連接實(shí)例。

    使用方法二

    當(dāng)要給線(xiàn)程初始化一個(gè)特殊值時(shí),需要自己實(shí)現(xiàn)ThreadLocal的子類(lèi)并重寫(xiě)該方法,通常使用一個(gè)內(nèi)部匿名類(lèi)對(duì)ThreadLocal進(jìn)行子類(lèi)化,EasyDBO中創(chuàng)建jdbc連接上下文就是這樣做的:

    public class JDBCContext{
     private static Logger logger = Logger.getLogger(JDBCContext.class);
     private DataSource ds;
     protected Connection connection;
     private boolean isValid = true;
     private static ThreadLocal jdbcContext;
     
     private JDBCContext(DataSource ds){
      this.ds = ds;
      createConnection();  
     }
     public static JDBCContext getJdbcContext(javax.sql.DataSource ds)
     {  
      if(jdbcContext==null)jdbcContext=new JDBCContextThreadLocal(ds);
      JDBCContext context = (JDBCContext) jdbcContext.get();
      if (context == null) {
       context = new JDBCContext(ds);
      }
      return context;
     }

     private static class JDBCContextThreadLocal extends ThreadLocal {
      public javax.sql.DataSource ds;
      public JDBCContextThreadLocal(javax.sql.DataSource ds)
      {
       this.ds=ds;
      }
      protected synchronized Object initialValue() {
       return new JDBCContext(ds);
      }
     }
    }

    使用單例模式,不同的線(xiàn)程調(diào)用getJdbcContext()獲得自己的jdbcContext,都是通過(guò)JDBCContextThreadLocal 內(nèi)置子類(lèi)來(lái)獲得JDBCContext對(duì)象的線(xiàn)程局部變量,這個(gè)變量是該線(xiàn)程所獨(dú)有的。

    posted on 2009-01-13 12:58 CONAN 閱讀(224) 評(píng)論(0)  編輯  收藏 所屬分類(lèi): J2SEJAVA
    主站蜘蛛池模板: 亚洲综合男人的天堂色婷婷| 国产精品亚洲AV三区| 免费中文熟妇在线影片| 99亚洲男女激情在线观看| 亚洲精品tv久久久久久久久| 最近免费中文字幕高清大全 | 久久久久久久99精品免费| 亚洲专区一路线二| 精品国产日韩亚洲一区| 免费精品国产自产拍在 | 日韩精品视频免费在线观看| 国产高清对白在线观看免费91 | 亚洲精品无码久久久久sm| 成人午夜视频免费| 久久这里只精品国产免费10| 国产成人人综合亚洲欧美丁香花| 亚洲成人在线网站| 伊在人亚洲香蕉精品区麻豆| 999国内精品永久免费观看| 一个人看的在线免费视频| 亚洲乱码一区av春药高潮| 亚洲精品无码不卡在线播放HE| 毛片免费vip会员在线看| 久9久9精品免费观看| 污污污视频在线免费观看| 亚洲国产熟亚洲女视频| 78成人精品电影在线播放日韩精品电影一区亚洲 | 久久亚洲精品无码av| 自怕偷自怕亚洲精品| 久久久久久亚洲精品不卡| 在线不卡免费视频| 亚洲日本在线免费观看| a毛片视频免费观看影院| 免费人成又黄又爽的视频在线电影| 亚洲乱码卡三乱码新区| 亚洲一区中文字幕久久| 精品国产_亚洲人成在线高清| 亚洲欧洲中文日韩av乱码| 免费中文字幕一级毛片| 免费黄色一级毛片| 在线a级毛片免费视频|