Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
+++ new/test/java/util/concurrent/ThreadPoolExecutor/ThrowingTasks.java
1 1 /*
2 2 * Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation.
8 8 *
9 9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 12 * version 2 for more details (a copy is included in the LICENSE file that
13 13 * accompanied this code).
14 14 *
15 15 * You should have received a copy of the GNU General Public License version
16 16 * 2 along with this work; if not, write to the Free Software Foundation,
17 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 18 *
19 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 20 * or visit www.oracle.com if you need additional information or have any
21 21 * questions.
22 22 */
23 23
24 24 /*
25 25 * @test
26 26 * @bug 6450200 6450205 6450207 6450211
27 27 * @summary Test proper handling of tasks that terminate abruptly
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
28 28 * @run main/othervm -XX:-UseVMInterruptibleIO ThrowingTasks
29 29 * @author Martin Buchholz
30 30 */
31 31
32 32 import java.security.*;
33 33 import java.util.*;
34 34 import java.util.concurrent.*;
35 35 import java.util.concurrent.atomic.*;
36 36
37 37 public class ThrowingTasks {
38 - final static Random rnd = new Random();
38 + static final Random rnd = new Random();
39 39
40 40 @SuppressWarnings("serial")
41 41 static class UncaughtExceptions
42 42 extends ConcurrentHashMap<Class<?>, Integer> {
43 43
44 44 void inc(Class<?> key) {
45 45 for (;;) {
46 46 Integer i = get(key);
47 47 if (i == null) {
48 48 if (putIfAbsent(key, 1) == null)
49 49 return;
50 50 } else {
51 51 if (replace(key, i, i + 1))
52 52 return;
53 53 }
54 54 }
55 55 }
56 56 }
57 57
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
58 58 @SuppressWarnings("serial")
59 59 static class UncaughtExceptionsTable
60 60 extends Hashtable<Class<?>, Integer> {
61 61
62 62 synchronized void inc(Class<?> key) {
63 63 Integer i = get(key);
64 64 put(key, (i == null) ? 1 : i + 1);
65 65 }
66 66 }
67 67
68 - final static UncaughtExceptions uncaughtExceptions
68 + static final UncaughtExceptions uncaughtExceptions
69 69 = new UncaughtExceptions();
70 - final static UncaughtExceptionsTable uncaughtExceptionsTable
70 + static final UncaughtExceptionsTable uncaughtExceptionsTable
71 71 = new UncaughtExceptionsTable();
72 - final static AtomicLong totalUncaughtExceptions
72 + static final AtomicLong totalUncaughtExceptions
73 73 = new AtomicLong(0);
74 - final static CountDownLatch uncaughtExceptionsLatch
74 + static final CountDownLatch uncaughtExceptionsLatch
75 75 = new CountDownLatch(24);
76 76
77 - final static Thread.UncaughtExceptionHandler handler
77 + static final Thread.UncaughtExceptionHandler handler
78 78 = new Thread.UncaughtExceptionHandler() {
79 79 public void uncaughtException(Thread t, Throwable e) {
80 80 check(! Thread.currentThread().isInterrupted());
81 81 totalUncaughtExceptions.getAndIncrement();
82 82 uncaughtExceptions.inc(e.getClass());
83 83 uncaughtExceptionsTable.inc(e.getClass());
84 84 uncaughtExceptionsLatch.countDown();
85 85 }};
86 86
87 - final static ThreadGroup tg = new ThreadGroup("Flaky");
87 + static final ThreadGroup tg = new ThreadGroup("Flaky");
88 88
89 - final static ThreadFactory tf = new ThreadFactory() {
89 + static final ThreadFactory tf = new ThreadFactory() {
90 90 public Thread newThread(Runnable r) {
91 91 Thread t = new Thread(tg, r);
92 92 t.setUncaughtExceptionHandler(handler);
93 93 return t;
94 94 }};
95 95
96 - final static RuntimeException rte = new RuntimeException();
97 - final static Error error = new Error();
98 - final static Throwable weird = new Throwable();
99 - final static Exception checkedException = new Exception();
96 + static final RuntimeException rte = new RuntimeException();
97 + static final Error error = new Error();
98 + static final Throwable weird = new Throwable();
99 + static final Exception checkedException = new Exception();
100 100
101 101 static class Thrower implements Runnable {
102 102 Throwable t;
103 103 Thrower(Throwable t) { this.t = t; }
104 104 @SuppressWarnings("deprecation")
105 105 public void run() { if (t != null) Thread.currentThread().stop(t); }
106 106 }
107 107
108 - final static Thrower noThrower = new Thrower(null);
109 - final static Thrower rteThrower = new Thrower(rte);
110 - final static Thrower errorThrower = new Thrower(error);
111 - final static Thrower weirdThrower = new Thrower(weird);
112 - final static Thrower checkedThrower = new Thrower(checkedException);
108 + static final Thrower noThrower = new Thrower(null);
109 + static final Thrower rteThrower = new Thrower(rte);
110 + static final Thrower errorThrower = new Thrower(error);
111 + static final Thrower weirdThrower = new Thrower(weird);
112 + static final Thrower checkedThrower = new Thrower(checkedException);
113 113
114 - final static List<Thrower> throwers = Arrays.asList(
114 + static final List<Thrower> throwers = Arrays.asList(
115 115 noThrower, rteThrower, errorThrower, weirdThrower, checkedThrower);
116 116
117 117 static class Flaky implements Runnable {
118 118 final Runnable beforeExecute;
119 119 final Runnable execute;
120 120 Flaky(Runnable beforeExecute,
121 121 Runnable execute) {
122 122 this.beforeExecute = beforeExecute;
123 123 this.execute = execute;
124 124 }
125 125 public void run() { execute.run(); }
126 126 }
127 127
128 128 static final List<Flaky> flakes = new ArrayList<Flaky>();
129 129 static {
130 130 for (Thrower x : throwers)
131 131 for (Thrower y : throwers)
132 132 flakes.add(new Flaky(x, y));
133 133 Collections.shuffle(flakes);
134 134 }
135 135
136 136 static final CountDownLatch allStarted = new CountDownLatch(flakes.size());
137 137 static final CountDownLatch allContinue = new CountDownLatch(1);
138 138
139 139 static class PermissiveSecurityManger extends SecurityManager {
140 140 public void checkPermission(Permission p) { /* bien sur, Monsieur */ }
141 141 }
142 142
143 143 static void checkTerminated(ThreadPoolExecutor tpe) {
144 144 try {
145 145 check(tpe.getQueue().isEmpty());
146 146 check(tpe.isShutdown());
147 147 check(tpe.isTerminated());
148 148 check(! tpe.isTerminating());
149 149 equal(tpe.getActiveCount(), 0);
150 150 equal(tpe.getPoolSize(), 0);
151 151 equal(tpe.getTaskCount(), tpe.getCompletedTaskCount());
152 152 check(tpe.awaitTermination(0, TimeUnit.SECONDS));
153 153 } catch (Throwable t) { unexpected(t); }
154 154 }
155 155
156 156 static class CheckingExecutor extends ThreadPoolExecutor {
157 157 CheckingExecutor() {
158 158 super(10, 10,
159 159 1L, TimeUnit.HOURS,
160 160 new LinkedBlockingQueue<Runnable>(),
161 161 tf);
162 162 }
163 163 @Override protected void beforeExecute(Thread t, Runnable r) {
164 164 allStarted.countDown();
165 165 if (allStarted.getCount() < getCorePoolSize())
166 166 try { allContinue.await(); }
167 167 catch (InterruptedException x) { unexpected(x); }
168 168 beforeExecuteCount.getAndIncrement();
169 169 check(! isTerminated());
170 170 ((Flaky)r).beforeExecute.run();
171 171 }
172 172 @Override protected void afterExecute(Runnable r, Throwable t) {
173 173 //System.out.println(tg.activeCount());
174 174 afterExecuteCount.getAndIncrement();
175 175 check(((Thrower)((Flaky)r).execute).t == t);
176 176 check(! isTerminated());
177 177 }
178 178 @Override protected void terminated() {
179 179 try {
180 180 terminatedCount.getAndIncrement();
181 181 if (rnd.nextBoolean()) {
182 182 check(isShutdown());
183 183 check(isTerminating());
184 184 check(! isTerminated());
185 185 check(! awaitTermination(0L, TimeUnit.MINUTES));
186 186 }
187 187 } catch (Throwable t) { unexpected(t); }
188 188 }
189 189 }
190 190
191 191 static final AtomicInteger beforeExecuteCount = new AtomicInteger(0);
192 192 static final AtomicInteger afterExecuteCount = new AtomicInteger(0);
193 193 static final AtomicInteger terminatedCount = new AtomicInteger(0);
194 194
195 195 private static void realMain(String[] args) throws Throwable {
196 196 if (rnd.nextBoolean())
197 197 System.setSecurityManager(new PermissiveSecurityManger());
198 198
199 199 CheckingExecutor tpe = new CheckingExecutor();
200 200
201 201 for (Runnable task : flakes)
202 202 tpe.execute(task);
203 203
204 204 if (rnd.nextBoolean()) {
205 205 allStarted.await();
206 206 equal(tpe.getTaskCount(),
207 207 (long) flakes.size());
208 208 equal(tpe.getCompletedTaskCount(),
209 209 (long) flakes.size() - tpe.getCorePoolSize());
210 210 }
211 211 allContinue.countDown();
212 212
213 213 //System.out.printf("thread count = %d%n", tg.activeCount());
214 214 uncaughtExceptionsLatch.await();
215 215
216 216 while (tg.activeCount() != tpe.getCorePoolSize() ||
217 217 tg.activeCount() != tpe.getCorePoolSize())
218 218 Thread.sleep(10);
219 219 equal(tg.activeCount(), tpe.getCorePoolSize());
220 220
221 221 tpe.shutdown();
222 222
223 223 check(tpe.awaitTermination(10L, TimeUnit.MINUTES));
224 224 checkTerminated(tpe);
225 225
226 226 //while (tg.activeCount() > 0) Thread.sleep(10);
227 227 //System.out.println(uncaughtExceptions);
228 228 List<Map<Class<?>, Integer>> maps
229 229 = new ArrayList<Map<Class<?>, Integer>>();
230 230 maps.add(uncaughtExceptions);
231 231 maps.add(uncaughtExceptionsTable);
232 232 for (Map<Class<?>, Integer> map : maps) {
233 233 equal(map.get(Exception.class), throwers.size());
234 234 equal(map.get(weird.getClass()), throwers.size());
235 235 equal(map.get(Error.class), throwers.size() + 1 + 2);
236 236 equal(map.get(RuntimeException.class), throwers.size() + 1);
237 237 equal(map.size(), 4);
238 238 }
239 239 equal(totalUncaughtExceptions.get(), 4L*throwers.size() + 4L);
240 240
241 241 equal(beforeExecuteCount.get(), flakes.size());
242 242 equal(afterExecuteCount.get(), throwers.size());
243 243 equal(tpe.getCompletedTaskCount(), (long) flakes.size());
244 244 equal(terminatedCount.get(), 1);
245 245
246 246 // check for termination operation idempotence
247 247 tpe.shutdown();
248 248 tpe.shutdownNow();
249 249 check(tpe.awaitTermination(10L, TimeUnit.MINUTES));
250 250 checkTerminated(tpe);
251 251 equal(terminatedCount.get(), 1);
252 252 }
253 253
254 254 //--------------------- Infrastructure ---------------------------
255 255 static volatile int passed = 0, failed = 0;
256 256 static void pass() {passed++;}
257 257 static void fail() {failed++; Thread.dumpStack();}
258 258 static void fail(String msg) {System.out.println(msg); fail();}
259 259 static void unexpected(Throwable t) {failed++; t.printStackTrace();}
260 260 static void check(boolean cond) {if (cond) pass(); else fail();}
261 261 static void equal(Object x, Object y) {
262 262 if (x == null ? y == null : x.equals(y)) pass();
263 263 else fail(x + " not equal to " + y);}
264 264 public static void main(String[] args) throws Throwable {
265 265 try {realMain(args);} catch (Throwable t) {unexpected(t);}
266 266 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
267 267 if (failed > 0) throw new AssertionError("Some tests failed");}
268 268 }
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX