001 // Copyright (c) 2001 Hursh Jain (http://www.mollypages.org) 002 // The Molly framework is freely distributable under the terms of an 003 // MIT-style license. For details, see the molly pages web site at: 004 // http://www.mollypages.org/. Use, modify, have fun ! 005 006 package fc.util; 007 008 import java.util.*; 009 import java.text.*; 010 011 /** 012 Useful to store thread-local instances of any object. This class is intended 013 for servlets/molly pages. Instead of static get/set methods, this class 014 must be instantiated and the instance methods used to get/set the objom 015 object. This allows multiple instances of this class in the webapp, with 016 each instance being able to get/set a separate object. 017 <p> 018 <font color=red><b>Each thread must remember to individually create a separate 019 object instance and store it via the set method</b></font>. The usage idiom 020 is: 021 <blockquote> 022 <pre> 023 <font color=blue> 024 //WebApp has a map of ThreadLocalObjects 025 ThreadLocalObject tl_obj = WebApp.getThreadLocalObject("foo"); 026 </font><font color=red> 027 if (tl_obj.isNull()) { 028 tl_obj.set(new obj()); 029 } 030 </font><font color=blue> 031 Object obj = tl_obj.get(); 032 </font> 033 </pre> 034 </blockquote> 035 Note, the lines in red are always needed anywhere/anytime this class is used. 036 */ 037 public final class ThreadLocalObject 038 { 039 public ThreadLocalObject() 040 { } 041 /* 042 Each get/set into the threadlocal must be seperately by each thread (the 043 initialValue() method is good for auto-assigning a new value but we 044 may need to assign a custom calendar value per thread, so we can't use 045 initialValue() 046 */ 047 private final ThreadLocal tl = new ThreadLocal(); 048 049 public Object get() 050 { 051 return (Object) tl.get(); 052 } 053 054 public void set(Object cal) 055 { 056 tl.set(cal); 057 } 058 059 public boolean isNull() 060 { 061 return tl.get() == null; 062 } 063 064 public static void main (String args[]) throws Exception 065 { 066 final ThreadLocalObject cal1 = new ThreadLocalObject(); 067 068 Thread t1 = new TestThread(false, cal1); 069 Thread t2 = new TestThread(false, cal1); 070 t1.start(); 071 t2.start(); 072 073 for (int n = 0; n < 100; n++) { 074 new TestThread(true, cal1).start(); 075 } 076 } 077 078 static class TestThread extends Thread 079 { 080 boolean timing_only = false; 081 ThreadLocalObject obj; 082 TestThread(boolean timing_only, ThreadLocalObject obj) { 083 this.timing_only = timing_only; 084 this.obj = obj; 085 } 086 087 public void run() 088 { 089 //warm up 090 if (obj.isNull()) { 091 obj.set(new Object()); 092 } 093 094 Watch w = new NanoWatch(); 095 w.start(); 096 if (obj.isNull()) { 097 obj.set(new Object()); 098 } 099 Object c = obj.get(); 100 w.stop(); 101 102 NumberFormat nf = NumberFormat.getNumberInstance(); 103 nf.setMinimumFractionDigits(2); 104 nf.setMaximumFractionDigits(2); 105 nf.setMinimumIntegerDigits(2); 106 107 System.out.println("[" + nf.format(w.getTime() / 1000000.00D) + " ms]" + Thread.currentThread() + "/Object-ID:[" + System.identityHashCode(c) + "] "+ c); 108 } 109 } 110 }