class TLtest extends Thread { public static void main (String [] args) { Data d = new Data (); new ThreadTest (d, "A").start (); new ThreadTest (d, "B").start (); } } class Data { private static ThreadLocal owner = new ThreadLocal () { public Object initialValue () { return ("0"); } }; /* A thread will call `set' to set a value it wants an instance of Data to associate with it and only it. */ synchronized public void set (String v){owner.set (v);} /* A thread will call `get' to get a value it wants an instance of Data to associate with it and only it. */ synchronized public String get (){return (String)owner.get();} } class ThreadTest extends Thread { public Data d; ThreadTest (Data d, String name) { super (name); this.d = d; } public void run () { int value = 0; int ref = 0; for (int i = 0; i < 20; i++) { int rand = (int)(Math.random ()*20); /* Read `value', ref is kept for comparison */ value = Integer.parseInt (d.get()); /* change `value' and ref by a random number, store `value'. */ value += rand; ref += rand; d.set (Integer.toString (value)); try { sleep((int)((Math.random() * 20))); } catch (InterruptedException e) {} } /* If a thread didn't have private value to attach to the instance of Data, results wouldn't be the same */ if (ref == value) System.out.println ("test OK."); else System.out.println ("test failed."); } }