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 006package fc.util; 007 008import java.util.*; 009import java.text.*; 010 011/** 012Useful to store thread-local instances of any object. This class is intended 013for servlets/molly pages. Instead of static get/set methods, this class 014must be instantiated and the instance methods used to get/set the objom 015object. This allows multiple instances of this class in the webapp, with 016each 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 019object instance and store it via the set method</b></font>. The usage idiom 020is: 021<blockquote> 022<pre> 023<font color=blue> 024//WebApp has a map of ThreadLocalObjects 025ThreadLocalObject tl_obj = WebApp.getThreadLocalObject("foo"); 026</font><font color=red> 027if (tl_obj.isNull()) { 028 tl_obj.set(new obj()); 029 } 030</font><font color=blue> 031Object obj = tl_obj.get(); 032</font> 033</pre> 034</blockquote> 035Note, the lines in red are always needed anywhere/anytime this class is used. 036*/ 037public final class ThreadLocalObject 038{ 039public ThreadLocalObject() 040 { } 041/* 042Each get/set into the threadlocal must be seperately by each thread (the 043initialValue() method is good for auto-assigning a new value but we 044may need to assign a custom calendar value per thread, so we can't use 045initialValue() 046*/ 047private final ThreadLocal tl = new ThreadLocal(); 048 049public Object get() 050 { 051 return (Object) tl.get(); 052 } 053 054public void set(Object cal) 055 { 056 tl.set(cal); 057 } 058 059public boolean isNull() 060 { 061 return tl.get() == null; 062 } 063 064public 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 078static 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}