1 /*
2  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3  *
4  * This code is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU General Public License version 2 only, as
6  * published by the Free Software Foundation.
7  *
8  * This code is distributed in the hope that it will be useful, but WITHOUT
9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
11  * version 2 for more details (a copy is included in the LICENSE file that
12  * accompanied this code).
13  *
14  * You should have received a copy of the GNU General Public License version
15  * 2 along with this work; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
17  *
18  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
19  * or visit www.oracle.com if you need additional information or have any
20  * questions.
21  */
22 
23 /*
24  * This file is available under and governed by the GNU General Public
25  * License version 2 only, as published by the Free Software Foundation.
26  * However, the following notice accompanied the original version of this
27  * file:
28  *
29  * Written by Doug Lea with assistance from members of JCP JSR-166
30  * Expert Group and released to the public domain, as explained at
31  * http://creativecommons.org/publicdomain/zero/1.0/
32  * Other contributors include Andrew Wright, Jeffrey Hayes,
33  * Pat Fisher, Mike Judd.
34  */
35 
36 import junit.framework.Test;
37 import junit.framework.TestSuite;
38 
39 public class ThreadLocalTest extends JSR166TestCase {
main(String[] args)40     public static void main(String[] args) {
41         main(suite(), args);
42     }
43 
suite()44     public static Test suite() {
45         return new TestSuite(ThreadLocalTest.class);
46     }
47 
48     static ThreadLocal<Integer> tl = new ThreadLocal<Integer>() {
49             public Integer initialValue() {
50                 return one;
51             }
52         };
53 
54     static InheritableThreadLocal<Integer> itl =
55         new InheritableThreadLocal<Integer>() {
56             protected Integer initialValue() {
57                 return zero;
58             }
59 
60             protected Integer childValue(Integer parentValue) {
61                 return new Integer(parentValue.intValue() + 1);
62             }
63         };
64 
65     /**
66      * remove causes next access to return initial value
67      */
testRemove()68     public void testRemove() {
69         assertSame(tl.get(), one);
70         tl.set(two);
71         assertSame(tl.get(), two);
72         tl.remove();
73         assertSame(tl.get(), one);
74     }
75 
76     /**
77      * remove in InheritableThreadLocal causes next access to return
78      * initial value
79      */
testRemoveITL()80     public void testRemoveITL() {
81         assertSame(itl.get(), zero);
82         itl.set(two);
83         assertSame(itl.get(), two);
84         itl.remove();
85         assertSame(itl.get(), zero);
86     }
87 
88     private class ITLThread extends Thread {
89         final int[] x;
ITLThread(int[] array)90         ITLThread(int[] array) { x = array; }
run()91         public void run() {
92             Thread child = null;
93             if (itl.get().intValue() < x.length - 1) {
94                 child = new ITLThread(x);
95                 child.start();
96             }
97             Thread.yield();
98 
99             int threadId = itl.get().intValue();
100             for (int j = 0; j < threadId; j++) {
101                 x[threadId]++;
102                 Thread.yield();
103             }
104 
105             if (child != null) { // Wait for child (if any)
106                 try {
107                     child.join();
108                 } catch (InterruptedException e) {
109                     threadUnexpectedException(e);
110                 }
111             }
112         }
113     }
114 
115     /**
116      * InheritableThreadLocal propagates generic values.
117      */
testGenericITL()118     public void testGenericITL() throws InterruptedException {
119         final int threadCount = 10;
120         final int[] x = new int[threadCount];
121         Thread progenitor = new ITLThread(x);
122         progenitor.start();
123         progenitor.join();
124         for (int i = 0; i < threadCount; i++) {
125             assertEquals(i, x[i]);
126         }
127     }
128 }
129