> > 2、你说的是对象池吧?
> >
> 这是两回事来的,对象池中的对象是取出来用的,所以多线程
>
> > 玫幕故堑ジ龅ジ龅亩韵舐铩?>
> 使用对象池是可以提高效率改善质量,但多数的情况下对普通
>
> >
> 目⑷嗽焙推胀ǖ南钅渴遣恢档di,因为还有大把大把更呆?
> 化的地方远比这里重要。
>
> 我第二个问题的意思是,当一个不用同步的线程安全的对象被
> 嘞叱掏狈梦适保前颜飧龆韵笞龀singlton的模式还是把?> 放到对象池中,那个效率高,为什么。

把不用同步的线程安全对象做成singleton模式是不合适的,因为这样可能会导致对象不安全,放到对象池中会安全一些,而且效率也不错 :)

> 谈到线程正好问个问题。
>
> 在jdk1.2中有一个threadLocal类,不知道大家用过没有。
> 以下是jdk的doc给出的注释。
> This class provides thread-local variables. These
> variables differ from their normal counterparts in
> that each thread that accesses one (via its get or
> set method) has its own, independently initialized
> copy of the variable. ThreadLocal instances are
> typically private static fields in classes that wish
> to associate state with a thread (e.g., a user ID or
> Transaction ID).
>
> For example, in the class below, the private static
> ThreadLocal instance (serialNum) maintains a "serial
> number" for each thread that invokes the class's
> static SerialNum.get() method, which returns the
> current thread's serial number. (A thread's serial
> number is assigned the first time it invokes
> SerialNum.get(), and remains unchanged on subsequent
> calls.)
>
> public class SerialNum {
> // The next serial number to be assigned
> private static int nextSerialNum = 0;
>
> private static ThreadLocal serialNum = new
> new ThreadLocal() {
> protected synchronized Object initialValue()
> lValue() {
> return new Integer(nextSerialNum++);
> }
> };
>
> public static int get() {
> return ((Integer)
> Integer) (serialNum.get())).intValue();
> }
> }
>
> Each thread holds an implicit reference to its copy
> of a thread-local variable as long as the thread is
> alive and the ThreadLocal instance is accessible;
> after a thread goes away, all of its copies of
> thread-local instances are subject to garbage
> collection (unless other references to these copies
> exist).
>
> 1 这样不就是意味着类中私有的static
> fields是线程安全的。
> 2 他的性能到底如何?
>

fields也不是很安全,从某个角度来说增加性能的时候牺牲了安全性和封装
ThreadLocal大多用做共享数据,比如有人在hibernate中使用它来模拟持久bean的共享性

> 把不用同步的线程安全对象做成singleton模式是不合适的,?> 为这样可能会导致对象不安全,放到对象池中会安全一些,而
> 倚室膊淮?:)

不用同步的线程安全对象当然做成static的了,singleton没必要,对象池是浪费

“不用同步的线程安全对象”名字好难理解哦
不用同步的线程对象?没有进行同步处理的线程对象?线程安全的对象?

> “不用同步的线程安全对象”名字好难理解哦
> 不用同步的线程对象?没有进行同步处理的线程对象?线程安
> 亩韵螅?

就是指不需要使用同步关键字的线程安全对象嘛

我的看法:如果你的类是线程安全,就没有必要使用对象池,直接使用singleton的对象就可以了,当然如果你的对象的创建代价很低,每次调用新创建也无妨!

至于使用对象池的条件是:
1。该对象线程不安全,同时只能有一个Thread访问。
2。该对象会被频繁创建,并且创建对象比较耗资源。

例如一个Servlet Container,request, response等对象(当然还应该包括来处理请求的thread本身)很显然是线程不安全的,如果每次调用(例如一次get或post请求)都创建相应对象,显然太过浪费和低效(经常每秒钟需要处理几百甚至上万次请求),这时使用对象池就很合适。而对于非SingleThreadedModel的Servlet,完全可以不必使用对象池(为了更高效避免反复创建,一般ServletContainer都会保存一个singleton的对象重复使用)

当然这里有一个例外:如果你的线程安全的对象是通过关键字synchronized来监视对象锁来保证的(也就是调用过程中可能存在锁等待),使用单一对象可能就有很大的性能问题(调用的相互等待),这时你可能需要使用对象池或者每次创建对象。

Regards
Joa

>1、只要类或者类的方法没有使用公共变量,则这个类或类的方法就是线程安全的。就不需要同步。

正确.

当且仅当在2个类或者方法需要访问到一个公共的资源时,需要synchronize机制.

btw,谨慎使用synchronize,不需要的地方不要用,很影响性能.

Azure_2003 :

最近又看了关于ThreadLocal的一些文献。
1 首先,不可否认的是,由于本身的原因它有一些性能原因。但在JDK1.4中已经改进不少。
2 他所持有的field,是线程安全的,可以被认为是每个Thread的单体对象。因为不太可能有别的线程访问它。
3 ThreadLocal大多用做共享数据,这是不错的,在hibernate中使用它来保存Session。这样对于每线程来说,就是线程安全的。

> Azure_2003 :
>
> 最近又看了关于ThreadLocal的一些文献。
> 1
> 1
> 首先,不可否认的是,由于本身的原因它有一些性能原因。但
> JDK1.4中已经改进不少。
> 2
> 2
> 他所持有的field,是线程安全的,可以被认为是每个Thread?> 单体对象。因为不太可能有别的线程访问它。
> 3
> 3
> ThreadLocal大多用做共享数据,这是不错的,在hibernate中
> 褂盟幢4Session。这样对于每线程来说,就是线程安全的
> ?

不太可能也不是不可能啊 ^_^

如果这么说的话,就做成static算了,如果在系统中只用一个实例,而且使用的地方比较多,做成singleton的话会安全一些

我来总结一下,看我总结的对不对,
首先说线程安全问题
说到底线程安全是针对数据来说的,不是针对对象中方法的,那么如果你在写程序过程中如果采用多线程,就要清楚在多个线程中是否存取同一个数据。如果采用单例模式,那么就要非常清楚这个单例对象中的方法存取的数据是否是线程间共享的。如果共享是不安全,如果确保不共项完全可以采用单例。
性能问题
很自然的得出结论,如果确保单例对象线程安全,那么他的性能应该比每次都要创建对象的性能好。

ThreadLocal instances are typically private static fields in classes that wish to associate state with a thread (e.g., a user ID or Transaction ID).

可以好好一下文档吗?

singlton的模式谨慎使用,是会影响性能,一般如果需要全局变量,如果你的应用是基于J2SE,那么使用threadLocal不失为一个方法,但是如果是基于容器的应用,就不适合使用ThreadLocal,使用PicoContainer之类AOP框架可以实现全局变量功能,性能比较优化,设计也很优雅。

问一下,这个问题我还是有点疑惑:
容器对于threadLocal的影响是在于那些方面?
是性能上的问题还是会造成错误?
我在Hibernate手册中看到,它的业务处理时对于Session的处理就是放在threadLocal中。有个文件叫HibernateUtil.java中有描述。Hibernate在容器中运行也应该没有什么问题吧。


java所有的对象都在堆上。对于一个进程中所有的线程来说,堆上的对象都是共享的。ThreadLocal用作线程局部存储(WIN32 API中也有),在多线程编程中很常用,一般用来存储线程的私有状态。完全不使用ThreadLocal的多线程编程也是可能的(使用同步和互斥等手段),但是就不如使用ThreadLocal方便了。