--- jsr166/src/test/tck/ThreadLocalTest.java 2003/12/27 19:26:44 1.4 +++ jsr166/src/test/tck/ThreadLocalTest.java 2021/01/27 01:57:24 1.19 @@ -1,41 +1,101 @@ /* * Written by Doug Lea with assistance from members of JCP JSR-166 * Expert Group and released to the public domain, as explained at - * http://creativecommons.org/licenses/publicdomain - * Other contributors include Andrew Wright, Jeffrey Hayes, - * Pat Fisher, Mike Judd. + * http://creativecommons.org/publicdomain/zero/1.0/ + * Other contributors include Andrew Wright, Jeffrey Hayes, + * Pat Fisher, Mike Judd. */ -import junit.framework.*; -import java.util.concurrent.Semaphore; +import junit.framework.Test; +import junit.framework.TestSuite; public class ThreadLocalTest extends JSR166TestCase { public static void main(String[] args) { - junit.textui.TestRunner.run(suite()); + main(suite(), args); } - + public static Test suite() { - return new TestSuite(ThreadLocalTest.class); + return new TestSuite(ThreadLocalTest.class); } - static ThreadLocal tl = new ThreadLocal() { - public Object initialValue() { - return new Integer(1); + static ThreadLocal tl = new ThreadLocal<>() { + public Item initialValue() { + return one; + } + }; + + static InheritableThreadLocal itl = + new InheritableThreadLocal<>() { + protected Item initialValue() { + return zero; + } + + protected Item childValue(Item parentValue) { + return new Item(parentValue.intValue() + 1); } }; - /** * remove causes next access to return initial value */ public void testRemove() { - Integer one = new Integer(1); - Integer two = new Integer(2); - assertEquals(tl.get(), one); + assertSame(tl.get(), one); tl.set(two); - assertEquals(tl.get(), two); + assertSame(tl.get(), two); tl.remove(); - assertEquals(tl.get(), one); + assertSame(tl.get(), one); + } + + /** + * remove in InheritableThreadLocal causes next access to return + * initial value + */ + public void testRemoveITL() { + assertSame(itl.get(), zero); + itl.set(two); + assertSame(itl.get(), two); + itl.remove(); + assertSame(itl.get(), zero); } -} + private class ITLThread extends Thread { + final int[] x; + ITLThread(int[] array) { x = array; } + public void run() { + Thread child = null; + if (itl.get().intValue() < x.length - 1) { + child = new ITLThread(x); + child.start(); + } + Thread.yield(); + + int threadId = itl.get().intValue(); + for (int j = 0; j < threadId; j++) { + x[threadId]++; + Thread.yield(); + } + + if (child != null) { // Wait for child (if any) + try { + child.join(); + } catch (InterruptedException e) { + threadUnexpectedException(e); + } + } + } + } + + /** + * InheritableThreadLocal propagates generic values. + */ + public void testGenericITL() throws InterruptedException { + final int threadCount = 10; + final int[] x = new int[threadCount]; + Thread progenitor = new ITLThread(x); + progenitor.start(); + progenitor.join(); + for (int i = 0; i < threadCount; i++) { + assertEquals(i, x[i]); + } + } +}