论坛首页 Java企业应用论坛

ThreadLocal示例

浏览 16628 次
精华帖 (2) :: 良好帖 (13) :: 新手帖 (13) :: 隐藏帖 (0)
作者 正文
   发表时间:2010-09-08  
liujun999999 写道
pengzhoushuo 写道

liujun999999 写道
我觉得效率是否真的有提高?
每个线程第一次调用ThreadLocal的时候会调用initialValue,也就是说其实每个线程还是创建了一个SimpleDateFormat啊

呵呵,是static变量,不会每次都调用initialValue,初始化的时候一次而已。

查看ThreadLocal类的doc

引用


protected T initialValue()
返回此线程局部变量的当前线程的“初始值”。线程第一次使用 get() 方法访问变量时将调用此方法,但如果线程之前调用了 set(T) 方法,则不会对该线程再调用 initialValue 方法。通常,此方法对每个线程最多调用一次,但如果在调用 get() 后又调用了 remove(),则可能再次调用此方法。
该实现返回 null;如果程序员希望线程局部变量具有 null 以外的值,则必须为 ThreadLocal 创建子类,并重写此方法。通常将使用匿名内部类完成此操作。

返回:
返回此线程局部变量的初始值

并不是创建ThreadLocal对象的时候调用一次

sorry,确实是我看错了,应该是单个线程只new一次,每个线程还是会各new一次的
0 请登录后投票
   发表时间:2010-09-08  
是个好点子   threadLocal 这个类还是蛮有创意的  在hibernate中 的openSession的实现就是使用了threadLocal实现的 

重要的是思想  看怎么用
0 请登录后投票
   发表时间:2010-09-08  
不错,典型的以空间换时间的实现,值得借鉴。
0 请登录后投票
   发表时间:2010-09-09  
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class T {
	 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
	 private static ThreadLocal threadLocal = new ThreadLocal() {   
	        protected synchronized Object initialValue() {   
	        	System.out.println("-----");
	            return new SimpleDateFormat(DATE_FORMAT);   
	        }   
	    };   
	    public static void main(String[] args) {
	    	Thread t1 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	Thread t2 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	Thread t3 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	t1.start();
	    	t2.start();
	    	t3.start();
	    }
}

输出 三次,为什么多次实例化了new SimpleDateFormat(DATE_FORMAT);   ?
怎么以空间换时间了?
0 请登录后投票
   发表时间:2010-09-09  
import java.text.SimpleDateFormat;
public class T {
	 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
	 private static ThreadLocal threadLocal = new ThreadLocal() {   
	        protected synchronized Object initialValue() {   
	        	System.out.println("-----");
	            return new SimpleDateFormat(DATE_FORMAT);   
	        }   
	    };   
	    public static void main(String[] args) {
	    	T tt1 = new T();
	    	T tt2 = new T();
	    	T tt3 = new T();
	    	tt1.threadLocal.get();
	    	tt2.threadLocal.get();
	    	tt3.threadLocal.get();
	    }
}

这样是输出了一次,在单线程里有效,与多线程无关吧?
0 请登录后投票
   发表时间:2010-09-09  
pouyang 写道
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
public class T {
	 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
	 private static ThreadLocal threadLocal = new ThreadLocal() {   
	        protected synchronized Object initialValue() {   
	        	System.out.println("-----");
	            return new SimpleDateFormat(DATE_FORMAT);   
	        }   
	    };   
	    public static void main(String[] args) {
	    	Thread t1 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	Thread t2 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	Thread t3 = new Thread(new Runnable() {
				public void run() {
					T t = new T();
					t.threadLocal.get();
				}
	    	});
	    	t1.start();
	    	t2.start();
	    	t3.start();
	    }
}

输出 三次,为什么多次实例化了new SimpleDateFormat(DATE_FORMAT);   ?
怎么以空间换时间了?

每个线程第一次获取都会初始化一次,你的实践验证能力很好,可能我开始描述的不是很清晰;
每一个线程初始化一次,每一个线程自身维护一个map,空间上占用内存较多,但不需要同步节约了时间;
0 请登录后投票
   发表时间:2010-09-09  
不好意思刚代码好像有点问题,但是这样还是输出三次

import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class T {
	 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
	 private static ThreadLocal threadLocal = new ThreadLocal() {   
	        protected synchronized Object initialValue() {   
	        	System.out.println("-----");
	            return new SimpleDateFormat(DATE_FORMAT);   
	        }   
	    };   
	    public static void main(String[] args) {
	    	  Thread t1 = new Thread(new Runnable() {   
	                public void run() {   
	                    T t = new T();   
	                    DateFormat df = (DateFormat) threadLocal.get();   
	                    if(df==null){   
	                        df = new SimpleDateFormat(DATE_FORMAT);   
	                        threadLocal.set(df);   
	                    } 
	                   //threadLocal.get();   
	                }   
	            });   
	            Thread t2 = new Thread(new Runnable() {   
	            	   public void run() {   
		                    T t = new T();   
		                    DateFormat df = (DateFormat) threadLocal.get();   
		                    if(df==null){   
		                        df = new SimpleDateFormat(DATE_FORMAT);   
		                        threadLocal.set(df);   
		                    } 
		                  // threadLocal.get();   
		                } 
	            });   
	            Thread t3 = new Thread(new Runnable() {   
	            	   public void run() {   
		                    T t = new T();   
		                    DateFormat df = (DateFormat) threadLocal.get();   
		                    if(df==null){   
		                        df = new SimpleDateFormat(DATE_FORMAT);   
		                        threadLocal.set(df);   
		                    } 
		                   //threadLocal.get();   
		                } 
	            });   
	            t1.start();   
	            t2.start();   
	            t3.start();   
	    }
}

说明每个线程的  threadLocal.get();   得到的都是null
0 请登录后投票
   发表时间:2010-09-09  
pouyang 写道
不好意思刚代码好像有点问题,但是这样还是输出三次

import java.text.DateFormat;
import java.text.SimpleDateFormat;
public class T {
	 private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";   
	 private static ThreadLocal threadLocal = new ThreadLocal() {   
	        protected synchronized Object initialValue() {   
	        	System.out.println("-----");
	            return new SimpleDateFormat(DATE_FORMAT);   
	        }   
	    };   
	    public static void main(String[] args) {
	    	  Thread t1 = new Thread(new Runnable() {   
	                public void run() {   
	                    T t = new T();   
	                    DateFormat df = (DateFormat) threadLocal.get();   
	                    if(df==null){   
	                        df = new SimpleDateFormat(DATE_FORMAT);   
	                        threadLocal.set(df);   
	                    } 
	                   //threadLocal.get();   
	                }   
	            });   
	            Thread t2 = new Thread(new Runnable() {   
	            	   public void run() {   
		                    T t = new T();   
		                    DateFormat df = (DateFormat) threadLocal.get();   
		                    if(df==null){   
		                        df = new SimpleDateFormat(DATE_FORMAT);   
		                        threadLocal.set(df);   
		                    } 
		                  // threadLocal.get();   
		                } 
	            });   
	            Thread t3 = new Thread(new Runnable() {   
	            	   public void run() {   
		                    T t = new T();   
		                    DateFormat df = (DateFormat) threadLocal.get();   
		                    if(df==null){   
		                        df = new SimpleDateFormat(DATE_FORMAT);   
		                        threadLocal.set(df);   
		                    } 
		                   //threadLocal.get();   
		                } 
	            });   
	            t1.start();   
	            t2.start();   
	            t3.start();   
	    }
}

说明每个线程的  threadLocal.get();   得到的都是null

每一次get的时候都调用getMap,返回一个map,判断map是否为null,如果为null,初始化;
因为每次获取的是线程自身的map,这个map第一次使用的时候肯定为null,调用初始化,输出了三次---------------,这么解释不知道您能否理解;
ThreadLocalMap getMap(Thread t) {
        return t.threadLocals;
}

0 请登录后投票
   发表时间:2010-09-09  
引用
每个线程第一次获取都会初始化一次,你的实践验证能力很好,可能我开始描述的不是很清晰;
每一个线程初始化一次,每一个线程自身维护一个map,空间上占用内存较多,但不需要同步节约了时间;

那把那个SimpleDateFormat对象的 static 修饰符去掉多好,
写成这样SimpleDateFormat s = new SimpleDateFormat(DATE_FORMAT);  就不需要考虑同步了,而且还不用去new ThreadLocal() ,
我的理解是用了ThreadLocal就可以跨类跨方法调用这个SimpleDateFormat 了(方法不用带参数)(robbin说的)
我是不是还没开窍啊。
0 请登录后投票
   发表时间:2010-09-09  
pengzhoushuo 写道
pengjunwu 写道
不明白 如果format 有2种或者更多 怎么处理
String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss"; 
String DATE_FORMAT = "yyyy/MM/dd HH:mm:ss"; .....

如果你有两个format,那就建多一个ThreadLocal变量呀,楼主想要表达的意思是说不要每次都new一个SimpleFormat,同个线程可以共享一个SimpleFormat。

我的意识是说 DATE_FORMAT 不能作为参数动态来创建SimpleFormat。
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics