Topic: 终于运用ThreadLocal实现了Connection和Transaction的管理

  Print this page

1.终于运用ThreadLocal实现了Connection和Transaction的管理 Copy to clipboard
Posted by: wes109
Posted on: 2004-04-23 13:11

测试用例(部分)通过


public void testBeginTransaction() throws TransactionException,SQLException {
Transaction tx = null;
try {
tx = ConnectionManager.beginTransaction();

assertEquals("aaa",findProduct16());

updateProduct16();
assertEquals("萝卜",findProduct16());

assertEquals("Alice Mutton",findProduct17());
updateProduct17();
//assertEquals("白菜",findProduct17());

tx.commit();
assertTrue(tx.wasCommitted());
/*
tx.commit();
assertTrue(tx.wasCommitted());
assertEquals("萝卜",findProduct16());
*/

/*
tx.rollback();
assertTrue(tx.wasRolledBack());
assertEquals("aaa",findProduct16());
assertEquals("Alice Mutton",findProduct17());
*/

} catch (TransactionException e) {
tx.rollback();
assertTrue(tx.wasRolledBack());
throw e;
} catch (SQLException e) {
tx.rollback();
assertTrue(tx.wasRolledBack());
//throw new TransactionException(e);
}

assertTrue(ConnectionManager.currentConnection().getAutoCommit());
}


更新了一下

dao.rar (780.49k)

2.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: wes109
Posted on: 2004-04-23 13:13

主要的管理类


public class ConnectionManager {
private static final ThreadLocal connection = new ThreadLocal();
private static ConnectionFactory factory;
private static boolean initialized = false;
private static final Log log = LogFactory.getLog(ConnectionManager.class);

private ConnectionManager() {
super();
}

private synchronized static void initialize() {
try {
factory = new Configuration().configure().buildConnectionFactory();
} catch (ConfigureException e) {
log.fatal(e);
}
log.info("ConnectionManager initialize success");
initialized = true;
}

public static Connection currentConnection() throws SQLException {
if(!initialized) {
initialize();
}
Connection conn = (Connection)connection.get();
if(conn == null) {
conn = factory.openConnection();
connection.set(conn);
}
return conn;
}

public static void closeConnection() throws SQLException {
Connection conn = (Connection)connection.get();
connection.set(null);
if(conn != null) {
conn.close();
}
}

public static Transaction beginTransaction() throws TransactionException{
Connection conn = null;
try {
conn = currentConnection();
} catch (SQLException e) {
log.error("Can't get current connection with SQLException:",e);
throw new TransactionException("Begin tracsaction fail with SQLException:", e);
}

return new TransactionFactory().beginTransaction(conn);
}
}

3.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: wes109
Posted on: 2004-04-23 15:38

我晕,怎么没人理俺?

4.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: linux_china
Posted on: 2004-04-23 16:44

看到你的这种眼神,就知道阁下对java的造诣颇深! 你的代码我看啦,想法非常棒,佩服啊,也加深了对ThreadLocal的更深的认识。其实用ThreadLocal管理资源确实不错,对事务管理(跨方法)等方面也有很多的好处。希望阁下能写篇ThreadLocal、资源管理方面的文章,让大家see啦,以体系你java高手高手高高手风范,不然这些东西(太抽象)放到这儿没人顶啊! Smile
期待你的好文章,当然是ThreadLocal和资源管理方面的啦! Smile
最后补充一句,logo不错啊! Smile

5.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: wes109
Posted on: 2004-04-26 09:23

我晕。。。。。。。。。。

在这里就不敢充高手了Big Smile

周六出去琅琊台胜地玩了一把,爽!呵呵

6.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: floater
Posted on: 2004-04-27 00:52

where is 琅琊台?

7.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: wes109
Posted on: 2004-04-27 08:33

http://www.sina-qd.com/qdtour_64.shtml

知道秦始皇的长生不老大梦吧?
知道徐福东渡吧?
知道那些关于日本人的笑话吧?

呵呵,其实那里离我们家不到50000米

8.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: floater
Posted on: 2004-04-27 21:51

Yea, that's why I asked. Thanks.

9.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: javait
Posted on: 2004-04-28 23:02

ThreadLocal 简介:

本质上来说ThreadLocal是一个WeakedHashMap,这个Map的key就是Thread.currentThread(),而value就是你要放到ThreadLocal里面的东西。通常我们要按照不同的Thread给它不同的值,所以就可以创建一个static的ThreadLocal,也就是在JVM里面存在了这样一个Map,然后你就可以按照key(当前线程)作为key来找Session。

ThreadLocal在JDK1.3以前的时候性能比较差,之所以差主要是因为Thread.currentThread()方法调用是一个native的方法,这个方法需要消耗很多时间才能够拿到当前线程,但是从JDK1.3以后,这个方法已经被大幅度优化,因此ThreadLocal的性能也有了本质的提高。目前ThreadLocal本身并不存在性能问题。

谢谢!
-javait

10.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: wes109
Posted on: 2004-04-29 08:25

我记得楼上的那一段是robbin写的(转载请注明出处!)

11.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: yamakasy
Posted on: 2004-04-29 12:34

不错,看来ThreadLocal 是很不错哦,而且效率优化了,值得使用.

12.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: 九佰
Posted on: 2004-05-08 14:59

ThreadLocal的设计与使用
来源: 天极网 作者: srx81
  早在Java 1.2推出之时,Java平台中就引入了一个新的支持:java.lang.ThreadLocal,给我们在编写多线程程序时提供了一种新的选择。使用这个工具类可以很简洁地编写出优美的多线程程序,虽然ThreadLocal非常有用,但是似乎现在了解它、使用它的朋友还不多。

  ThreadLocal是什么

  ThreadLocal是什么呢?其实ThreadLocal并非是一个线程的本地实现版本,它并不是一个Thread,而是thread local variable(线程局部变量)。也许把它命名为ThreadLocalVar更加合适。线程局部变量(ThreadLocal)其实的功用非常简单,就是为每一个使用该变量的线程都提供一个变量值的副本,是每一个线程都可以独立地改变自己的副本,而不会和其它线程的副本冲突。从线程的角度看,就好像每一个线程都完全拥有该变量。线程局部变量并不是Java的新发明,在其它的一些语言编译器实现(如IBM XL FORTRAN)中,它在语言的层次提供了直接的支持。因为Java中没有提供在语言层次的直接支持,而是提供了一个ThreadLocal的类来提供支持,所以,在Java中编写线程局部变量的代码相对比较笨拙,这也许是线程局部变量没有在Java中得到很好的普及的一个原因吧。

  ThreadLocal的设计

  首先看看ThreadLocal的接口:

  Object get() ; // 返回当前线程的线程局部变量副本 protected Object initialValue(); // 返回该线程局部变量的当前线程的初始值void set(Object value); // 设置当前线程的线程局部变量副本的值

  ThreadLocal有3个方法,其中值得注意的是initialValue(),该方法是一个protected的方法,显然是为了子类重写而特意实现的。该方法返回当前线程在该线程局部变量的初始值,这个方法是一个延迟调用方法,在一个线程第1次调用get()或者set(Object)时才执行,并且仅执行1次。ThreadLocal中的确实实现直接返回一个null:

protected Object initialValue() { return null; }

  ThreadLocal是如何做到为每一个线程维护变量的副本的呢?其实实现的思路很简单,在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。比如下面的示例实现:

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;
 }
}

  当然,这并不是一个工业强度的实现,但JDK中的ThreadLocal的实现总体思路也类似于此。

  ThreadLocal的使用

  如果希望线程局部变量初始化其它值,那么需要自己实现ThreadLocal的子类并重写该方法,通常使用一个内部匿名类对ThreadLocal进行子类化,比如下面的例子,SerialNum类为每一个类分配一个序号:

public class SerialNum
{
 // The next serial number to be assigned

 private static int nextSerialNum = 0;
 private static ThreadLocal serialNum = new ThreadLocal()
 {
  protected synchronized Object initialValue()
  {
   return new Integer(nextSerialNum++);
  }
 };

 public static int get()
 {
  return ((Integer) (serialNum.get())).intValue();
 }
}

  SerialNum类的使用将非常地简单,因为get()方法是static的,所以在需要获取当前线程的序号时,简单地调用:

int serial = SerialNum.get();

  即可。

  在线程是活动的并且ThreadLocal对象是可访问的时,该线程就持有一个到该线程局部变量副本的隐含引用,当该线程运行结束后,该线程拥有的所以线程局部变量的副本都将失效,并等待垃圾收集器收集。

  ThreadLocal与其它同步机制的比较

  ThreadLocal和其它同步机制相比有什么优势呢?ThreadLocal和其它所有的同步机制都是为了解决多线程中的对同一变量的访问冲突,在普通的同步机制中,是通过对象加锁来实现多个线程对同一变量的安全访问的。这时该变量是多个线程共享的,使用这种同步机制需要很细致地分析在什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放该对象的锁等等很多。所有这些都是因为多个线程共享了资源造成的。ThreadLocal就从另一个角度来解决多线程的并发访问,ThreadLocal会为每一个线程维护一个和该线程绑定的变量的副本,从而隔离了多个线程的数据,每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的整个变量封装进ThreadLocal,或者把该对象的特定于线程的状态封装进ThreadLocal。

  由于ThreadLocal中可以持有任何类型的对象,所以使用ThreadLocal get当前线程的值是需要进行强制类型转换。但随着新的Java版本(1.5)将模版的引入,新的支持模版参数的ThreadLocal<T>类将从中受益。也可以减少强制类型转换,并将一些错误检查提前到了编译期,将一定程度地简化ThreadLocal的使用。

  总结

  当然ThreadLocal并不能替代同步机制,两者面向的问题领域不同。同步机制是为了同步多个线程对相同资源的并发访问,是为了多个线程之间进行通信的有效方式;而ThreadLocal是隔离多个线程的数据共享,从根本上就不在多个线程之间共享资源(变量),这样当然不需要对多个线程进行同步了。所以,如果你需要进行多个线程之间进行通信,则使用同步机制;如果需要隔离多个线程之间的共享冲突,可以使用ThreadLocal,这将极大地简化你的程序,使程序更加易读、简洁。

13.Re:终于运用ThreadLocal实现了Connection和Transaction的管理 [Re: wes109] Copy to clipboard
Posted by: sunfmin
Posted on: 2004-11-24 15:37

在ThreadLocal类中有一个Map,用于存储每一个线程的变量的副本。

在看了j2sdk1.4.2的src之后,感觉并非如此。

并非在ThreadLocal中有这样一个Map,而是在每个Thread中存在这样一个Map。
具体是ThreadLocal.ThreadLocalMap。
当用set时候,它是往当前线程里面的Map里 put 的key是当前的ThreadLocal对象。
而不是把当前Thread作为Key值put到ThreadLocal中的Map里。


   Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent
Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1
客服电话 18559299278    客服信箱 714923@qq.com    客服QQ 714923