ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/jsr166/jsr166/src/test/tck/CyclicBarrierTest.java
(Generate patch)

Comparing jsr166/src/test/tck/CyclicBarrierTest.java (file contents):
Revision 1.7 by dl, Fri Jan 9 14:45:58 2004 UTC vs.
Revision 1.34 by jsr166, Mon Sep 9 00:46:44 2019 UTC

# Line 1 | Line 1
1   /*
2   * Written by Doug Lea with assistance from members of JCP JSR-166
3   * Expert Group and released to the public domain, as explained at
4 < * http://creativecommons.org/licenses/publicdomain
5 < * Other contributors include Andrew Wright, Jeffrey Hayes,
6 < * Pat Fisher, Mike Judd.
4 > * http://creativecommons.org/publicdomain/zero/1.0/
5 > * Other contributors include Andrew Wright, Jeffrey Hayes,
6 > * Pat Fisher, Mike Judd.
7   */
8  
9 < import junit.framework.*;
10 < import java.util.*;
11 < import java.util.concurrent.*;
9 > import static java.util.concurrent.TimeUnit.MILLISECONDS;
10  
11 < public class CyclicBarrierTest extends JSR166TestCase{
11 > import java.util.concurrent.BrokenBarrierException;
12 > import java.util.concurrent.CountDownLatch;
13 > import java.util.concurrent.CyclicBarrier;
14 > import java.util.concurrent.ExecutorService;
15 > import java.util.concurrent.Executors;
16 > import java.util.concurrent.ThreadLocalRandom;
17 > import java.util.concurrent.TimeoutException;
18 > import java.util.concurrent.atomic.AtomicInteger;
19 >
20 > import junit.framework.Test;
21 > import junit.framework.TestSuite;
22 >
23 > public class CyclicBarrierTest extends JSR166TestCase {
24      public static void main(String[] args) {
25 <        junit.textui.TestRunner.run (suite());  
25 >        main(suite(), args);
26      }
27      public static Test suite() {
28 <        return new TestSuite(CyclicBarrierTest.class);
28 >        return new TestSuite(CyclicBarrierTest.class);
29      }
30  
31 <    private volatile int countAction;
32 <    private class MyAction implements Runnable {
33 <        public void run() { ++countAction; }
31 >    /**
32 >     * Spin-waits till the number of waiters == numberOfWaiters.
33 >     */
34 >    void awaitNumberWaiting(CyclicBarrier barrier, int numberOfWaiters) {
35 >        long startTime = System.nanoTime();
36 >        while (barrier.getNumberWaiting() != numberOfWaiters) {
37 >            if (millisElapsedSince(startTime) > LONG_DELAY_MS)
38 >                fail("timed out");
39 >            Thread.yield();
40 >        }
41      }
42 <    
42 >
43      /**
44 <     * Creating with negative parties throws IAE
44 >     * Creating with negative parties throws IllegalArgumentException
45       */
46      public void testConstructor1() {
47          try {
48              new CyclicBarrier(-1, (Runnable)null);
49              shouldThrow();
50 <        } catch(IllegalArgumentException e){}
50 >        } catch (IllegalArgumentException success) {}
51      }
52  
53      /**
54 <     * Creating with negative parties and no action throws IAE
54 >     * Creating with negative parties and no action throws
55 >     * IllegalArgumentException
56       */
57      public void testConstructor2() {
58          try {
59              new CyclicBarrier(-1);
60              shouldThrow();
61 <        } catch(IllegalArgumentException e){}
61 >        } catch (IllegalArgumentException success) {}
62      }
63  
64      /**
# Line 48 | Line 66 | public class CyclicBarrierTest extends J
66       */
67      public void testGetParties() {
68          CyclicBarrier b = new CyclicBarrier(2);
69 <        assertEquals(2, b.getParties());
69 >        assertEquals(2, b.getParties());
70          assertEquals(0, b.getNumberWaiting());
71      }
72  
73      /**
74       * A 1-party barrier triggers after single await
75       */
76 <    public void testSingleParty() {
77 <        try {
78 <            CyclicBarrier b = new CyclicBarrier(1);
79 <            assertEquals(1, b.getParties());
80 <            assertEquals(0, b.getNumberWaiting());
81 <            b.await();
82 <            b.await();
65 <            assertEquals(0, b.getNumberWaiting());
66 <        }
67 <        catch(Exception e) {
68 <            unexpectedException();
69 <        }
76 >    public void testSingleParty() throws Exception {
77 >        CyclicBarrier b = new CyclicBarrier(1);
78 >        assertEquals(1, b.getParties());
79 >        assertEquals(0, b.getNumberWaiting());
80 >        b.await();
81 >        b.await();
82 >        assertEquals(0, b.getNumberWaiting());
83      }
84 <    
84 >
85      /**
86       * The supplied barrier action is run at barrier
87       */
88 <    public void testBarrierAction() {
89 <        try {
90 <            countAction = 0;
91 <            CyclicBarrier b = new CyclicBarrier(1, new MyAction());
92 <            assertEquals(1, b.getParties());
93 <            assertEquals(0, b.getNumberWaiting());
94 <            b.await();
95 <            b.await();
96 <            assertEquals(0, b.getNumberWaiting());
97 <            assertEquals(countAction, 2);
98 <        }
86 <        catch(Exception e) {
87 <            unexpectedException();
88 <        }
88 >    public void testBarrierAction() throws Exception {
89 >        final AtomicInteger count = new AtomicInteger(0);
90 >        final Runnable incCount = new Runnable() { public void run() {
91 >            count.getAndIncrement(); }};
92 >        CyclicBarrier b = new CyclicBarrier(1, incCount);
93 >        assertEquals(1, b.getParties());
94 >        assertEquals(0, b.getNumberWaiting());
95 >        b.await();
96 >        b.await();
97 >        assertEquals(0, b.getNumberWaiting());
98 >        assertEquals(2, count.get());
99      }
100  
101      /**
102       * A 2-party/thread barrier triggers after both threads invoke await
103       */
104 <    public void testTwoParties() {
104 >    public void testTwoParties() throws Exception {
105          final CyclicBarrier b = new CyclicBarrier(2);
106 <        Thread t = new Thread(new Runnable() {
107 <                public void run() {
108 <                    try {
109 <                        b.await();
110 <                        b.await();
111 <                        b.await();
112 <                        b.await();
113 <                    } catch(Exception e){
114 <                        threadUnexpectedException();
115 <                    }}});
116 <
117 <        try {
118 <            t.start();
109 <            b.await();
110 <            b.await();
111 <            b.await();
112 <            b.await();
113 <            t.join();
114 <        } catch(Exception e){
115 <            unexpectedException();
116 <        }
106 >        Thread t = newStartedThread(new CheckedRunnable() {
107 >            public void realRun() throws Exception {
108 >                b.await();
109 >                b.await();
110 >                b.await();
111 >                b.await();
112 >            }});
113 >
114 >        b.await();
115 >        b.await();
116 >        b.await();
117 >        b.await();
118 >        awaitTermination(t);
119      }
120  
119
121      /**
122       * An interruption in one party causes others waiting in await to
123       * throw BrokenBarrierException
124       */
125      public void testAwait1_Interrupted_BrokenBarrier() {
126          final CyclicBarrier c = new CyclicBarrier(3);
127 <        Thread t1 = new Thread(new Runnable() {
128 <                public void run() {
129 <                    try {
130 <                        c.await();
131 <                        threadShouldThrow();
132 <                    } catch(InterruptedException success){}                
133 <                    catch(Exception b){
134 <                        threadUnexpectedException();
135 <                    }
136 <                }
137 <            });
138 <        Thread t2 = new Thread(new Runnable() {
139 <                public void run() {
140 <                    try {
141 <                        c.await();
142 <                        threadShouldThrow();                        
143 <                    } catch(BrokenBarrierException success){
144 <                    } catch(Exception i){
144 <                        threadUnexpectedException();
145 <                    }
146 <                }
147 <            });
148 <        try {
149 <            t1.start();
150 <            t2.start();
151 <            Thread.sleep(SHORT_DELAY_MS);
152 <            t1.interrupt();
153 <            t1.join();
154 <            t2.join();
155 <        } catch(InterruptedException e){
156 <            unexpectedException();
157 <        }
127 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
128 >        Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
129 >            public void realRun() throws Exception {
130 >                pleaseInterrupt.countDown();
131 >                c.await();
132 >            }};
133 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
134 >            public void realRun() throws Exception {
135 >                pleaseInterrupt.countDown();
136 >                c.await();
137 >            }};
138 >
139 >        t1.start();
140 >        t2.start();
141 >        await(pleaseInterrupt);
142 >        t1.interrupt();
143 >        awaitTermination(t1);
144 >        awaitTermination(t2);
145      }
146  
147      /**
148       * An interruption in one party causes others waiting in timed await to
149       * throw BrokenBarrierException
150       */
151 <    public void testAwait2_Interrupted_BrokenBarrier() {
152 <      final CyclicBarrier c = new CyclicBarrier(3);
153 <        Thread t1 = new Thread(new Runnable() {
154 <                public void run() {
155 <                    try {
156 <                        c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
157 <                        threadShouldThrow();
158 <                    } catch(InterruptedException success){
159 <                    } catch(Exception b){
160 <                        threadUnexpectedException();
161 <                    }
162 <                }
163 <            });
164 <        Thread t2 = new Thread(new Runnable() {
165 <                public void run() {
166 <                    try {
167 <                        c.await(LONG_DELAY_MS, TimeUnit.MILLISECONDS);
168 <                        threadShouldThrow();                        
169 <                    } catch(BrokenBarrierException success){
170 <                    } catch(Exception i){
184 <                        threadUnexpectedException();
185 <                    }
186 <                }
187 <            });
188 <        try {
189 <            t1.start();
190 <            t2.start();
191 <            Thread.sleep(SHORT_DELAY_MS);
192 <            t1.interrupt();
193 <            t1.join();
194 <            t2.join();
195 <        } catch(InterruptedException e){
196 <            unexpectedException();
197 <        }
151 >    public void testAwait2_Interrupted_BrokenBarrier() throws Exception {
152 >        final CyclicBarrier c = new CyclicBarrier(3);
153 >        final CountDownLatch pleaseInterrupt = new CountDownLatch(2);
154 >        Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
155 >            public void realRun() throws Exception {
156 >                pleaseInterrupt.countDown();
157 >                c.await(LONG_DELAY_MS, MILLISECONDS);
158 >            }};
159 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
160 >            public void realRun() throws Exception {
161 >                pleaseInterrupt.countDown();
162 >                c.await(LONG_DELAY_MS, MILLISECONDS);
163 >            }};
164 >
165 >        t1.start();
166 >        t2.start();
167 >        await(pleaseInterrupt);
168 >        t1.interrupt();
169 >        awaitTermination(t1);
170 >        awaitTermination(t2);
171      }
172 <    
172 >
173      /**
174       * A timeout in timed await throws TimeoutException
175       */
176 <    public void testAwait3_TimeOutException() {
176 >    public void testAwait3_TimeoutException() throws InterruptedException {
177          final CyclicBarrier c = new CyclicBarrier(2);
178 <        Thread t = new Thread(new Runnable() {
179 <                public void run() {
180 <                    try {
181 <                        c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
182 <                        threadShouldThrow();
183 <                    } catch(TimeoutException success){
184 <                    } catch(Exception b){
185 <                        threadUnexpectedException();
186 <                        
187 <                    }
188 <                }
216 <            });
217 <        try {
218 <            t.start();
219 <            t.join();
220 <        } catch(InterruptedException e){
221 <            unexpectedException();
222 <        }
178 >        Thread t = newStartedThread(new CheckedRunnable() {
179 >            public void realRun() throws Exception {
180 >                long startTime = System.nanoTime();
181 >                try {
182 >                    c.await(timeoutMillis(), MILLISECONDS);
183 >                    shouldThrow();
184 >                } catch (TimeoutException success) {}
185 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
186 >            }});
187 >
188 >        awaitTermination(t);
189      }
190  
191      /**
192       * A timeout in one party causes others waiting in timed await to
193       * throw BrokenBarrierException
194       */
195 <    public void testAwait4_Timeout_BrokenBarrier() {
196 <      final CyclicBarrier c = new CyclicBarrier(3);
197 <        Thread t1 = new Thread(new Runnable() {
198 <                public void run() {
199 <                    try {
200 <                        c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
201 <                        threadShouldThrow();
202 <                    } catch(TimeoutException success){
203 <                    } catch(Exception b){
204 <                        threadUnexpectedException();
205 <                    }
206 <                }
207 <            });
208 <        Thread t2 = new Thread(new Runnable() {
209 <                public void run() {
210 <                    try {
211 <                        c.await(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS);
212 <                        threadShouldThrow();                        
213 <                    } catch(BrokenBarrierException success){
214 <                    } catch(Exception i){
215 <                        threadUnexpectedException();
216 <                    }
251 <                }
252 <            });
253 <        try {
254 <            t1.start();
255 <            t2.start();
256 <            t1.join();
257 <            t2.join();
258 <        } catch(InterruptedException e){
259 <            unexpectedException();
260 <        }
195 >    public void testAwait4_Timeout_BrokenBarrier() throws InterruptedException {
196 >        final CyclicBarrier c = new CyclicBarrier(3);
197 >        Thread t1 = newStartedThread(new CheckedRunnable() {
198 >            public void realRun() throws Exception {
199 >                try {
200 >                    c.await(LONG_DELAY_MS, MILLISECONDS);
201 >                    shouldThrow();
202 >                } catch (BrokenBarrierException success) {}
203 >            }});
204 >        Thread t2 = newStartedThread(new CheckedRunnable() {
205 >            public void realRun() throws Exception {
206 >                awaitNumberWaiting(c, 1);
207 >                long startTime = System.nanoTime();
208 >                try {
209 >                    c.await(timeoutMillis(), MILLISECONDS);
210 >                    shouldThrow();
211 >                } catch (TimeoutException success) {}
212 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
213 >            }});
214 >
215 >        awaitTermination(t1);
216 >        awaitTermination(t2);
217      }
218  
219      /**
220       * A timeout in one party causes others waiting in await to
221       * throw BrokenBarrierException
222       */
223 <    public void testAwait5_Timeout_BrokenBarrier() {
224 <      final CyclicBarrier c = new CyclicBarrier(3);
225 <        Thread t1 = new Thread(new Runnable() {
226 <                public void run() {
227 <                    try {
228 <                        c.await(SHORT_DELAY_MS, TimeUnit.MILLISECONDS);
229 <                        threadShouldThrow();
230 <                    } catch(TimeoutException success){
231 <                    } catch(Exception b){
232 <                        threadUnexpectedException();
233 <                    }
234 <                }
235 <            });
236 <        Thread t2 = new Thread(new Runnable() {
237 <                public void run() {
238 <                    try {
239 <                        c.await();
240 <                        threadShouldThrow();                        
241 <                    } catch(BrokenBarrierException success){
242 <                    } catch(Exception i){
243 <                        threadUnexpectedException();
244 <                    }
289 <                }
290 <            });
291 <        try {
292 <            t1.start();
293 <            t2.start();
294 <            t1.join();
295 <            t2.join();
296 <        } catch(InterruptedException e){
297 <            unexpectedException();
298 <        }
223 >    public void testAwait5_Timeout_BrokenBarrier() throws InterruptedException {
224 >        final CyclicBarrier c = new CyclicBarrier(3);
225 >        Thread t1 = newStartedThread(new CheckedRunnable() {
226 >            public void realRun() throws Exception {
227 >                try {
228 >                    c.await();
229 >                    shouldThrow();
230 >                } catch (BrokenBarrierException success) {}
231 >            }});
232 >        Thread t2 = newStartedThread(new CheckedRunnable() {
233 >            public void realRun() throws Exception {
234 >                awaitNumberWaiting(c, 1);
235 >                long startTime = System.nanoTime();
236 >                try {
237 >                    c.await(timeoutMillis(), MILLISECONDS);
238 >                    shouldThrow();
239 >                } catch (TimeoutException success) {}
240 >                assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
241 >            }});
242 >
243 >        awaitTermination(t1);
244 >        awaitTermination(t2);
245      }
246 <    
246 >
247      /**
248       * A reset of an active barrier causes waiting threads to throw
249       * BrokenBarrierException
250       */
251 <    public void testReset_BrokenBarrier() {
251 >    public void testReset_BrokenBarrier() throws InterruptedException {
252          final CyclicBarrier c = new CyclicBarrier(3);
253 <        Thread t1 = new Thread(new Runnable() {
254 <                public void run() {
255 <                    try {
256 <                        c.await();
257 <                        threadShouldThrow();
258 <                    } catch(BrokenBarrierException success){}                
259 <                    catch(Exception b){
260 <                        threadUnexpectedException();
261 <                    }
262 <                }
263 <            });
264 <        Thread t2 = new Thread(new Runnable() {
265 <                public void run() {
266 <                    try {
267 <                        c.await();
268 <                        threadShouldThrow();                        
269 <                    } catch(BrokenBarrierException success){
270 <                    } catch(Exception i){
271 <                        threadUnexpectedException();
272 <                    }
327 <                }
328 <            });
329 <        try {
330 <            t1.start();
331 <            t2.start();
332 <            Thread.sleep(SHORT_DELAY_MS);
333 <            c.reset();
334 <            t1.join();
335 <            t2.join();
336 <        } catch(InterruptedException e){
337 <            unexpectedException();
338 <        }
253 >        final CountDownLatch pleaseReset = new CountDownLatch(2);
254 >        Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
255 >            public void realRun() throws Exception {
256 >                pleaseReset.countDown();
257 >                c.await();
258 >            }};
259 >        Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
260 >            public void realRun() throws Exception {
261 >                pleaseReset.countDown();
262 >                c.await();
263 >            }};
264 >
265 >        t1.start();
266 >        t2.start();
267 >        await(pleaseReset);
268 >
269 >        awaitNumberWaiting(c, 2);
270 >        c.reset();
271 >        awaitTermination(t1);
272 >        awaitTermination(t2);
273      }
274  
275      /**
276       * A reset before threads enter barrier does not throw
277       * BrokenBarrierException
278       */
279 <    public void testReset_NoBrokenBarrier() {
279 >    public void testReset_NoBrokenBarrier() throws Exception {
280          final CyclicBarrier c = new CyclicBarrier(3);
281 <        Thread t1 = new Thread(new Runnable() {
282 <                public void run() {
283 <                    try {
284 <                        c.await();
285 <                    } catch(Exception b){
286 <                        threadUnexpectedException();
287 <                    }
288 <                }
289 <            });
290 <        Thread t2 = new Thread(new Runnable() {
291 <                public void run() {
292 <                    try {
293 <                        c.await();
294 <                    } catch(Exception i){
295 <                        threadUnexpectedException();
296 <                    }
297 <                }
298 <            });
299 <        try {
300 <            c.reset();
281 >        c.reset();
282 >
283 >        Thread t1 = newStartedThread(new CheckedRunnable() {
284 >            public void realRun() throws Exception {
285 >                c.await();
286 >            }});
287 >        Thread t2 = newStartedThread(new CheckedRunnable() {
288 >            public void realRun() throws Exception {
289 >                c.await();
290 >            }});
291 >
292 >        c.await();
293 >        awaitTermination(t1);
294 >        awaitTermination(t2);
295 >    }
296 >
297 >    /**
298 >     * Reset of a non-broken barrier does not break barrier
299 >     */
300 >    public void testResetWithoutBreakage() throws Exception {
301 >        final CyclicBarrier barrier = new CyclicBarrier(3);
302 >        for (int i = 0; i < 3; i++) {
303 >            final CyclicBarrier start = new CyclicBarrier(3);
304 >            Thread t1 = newStartedThread(new CheckedRunnable() {
305 >                public void realRun() throws Exception {
306 >                    start.await();
307 >                    barrier.await();
308 >                }});
309 >
310 >            Thread t2 = newStartedThread(new CheckedRunnable() {
311 >                public void realRun() throws Exception {
312 >                    start.await();
313 >                    barrier.await();
314 >                }});
315 >
316 >            start.await();
317 >            barrier.await();
318 >            awaitTermination(t1);
319 >            awaitTermination(t2);
320 >            assertFalse(barrier.isBroken());
321 >            assertEquals(0, barrier.getNumberWaiting());
322 >            if (i == 1) barrier.reset();
323 >            assertFalse(barrier.isBroken());
324 >            assertEquals(0, barrier.getNumberWaiting());
325 >        }
326 >    }
327 >
328 >    /**
329 >     * Reset of a barrier after interruption reinitializes it.
330 >     */
331 >    public void testResetAfterInterrupt() throws Exception {
332 >        final CyclicBarrier barrier = new CyclicBarrier(3);
333 >        for (int i = 0; i < 2; i++) {
334 >            final CyclicBarrier start = new CyclicBarrier(3);
335 >            Thread t1 = new ThreadShouldThrow(InterruptedException.class) {
336 >                public void realRun() throws Exception {
337 >                    start.await();
338 >                    barrier.await();
339 >                }};
340 >
341 >            Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
342 >                public void realRun() throws Exception {
343 >                    start.await();
344 >                    barrier.await();
345 >                }};
346 >
347              t1.start();
348              t2.start();
349 <            c.await();
350 <            t1.join();
351 <            t2.join();
352 <        } catch(Exception e){
353 <            unexpectedException();
349 >            start.await();
350 >            t1.interrupt();
351 >            awaitTermination(t1);
352 >            awaitTermination(t2);
353 >            assertTrue(barrier.isBroken());
354 >            assertEquals(0, barrier.getNumberWaiting());
355 >            barrier.reset();
356 >            assertFalse(barrier.isBroken());
357 >            assertEquals(0, barrier.getNumberWaiting());
358 >        }
359 >    }
360 >
361 >    /**
362 >     * Reset of a barrier after timeout reinitializes it.
363 >     */
364 >    public void testResetAfterTimeout() throws Exception {
365 >        final CyclicBarrier barrier = new CyclicBarrier(3);
366 >        for (int i = 0; i < 2; i++) {
367 >            assertEquals(0, barrier.getNumberWaiting());
368 >            Thread t1 = newStartedThread(new CheckedRunnable() {
369 >                public void realRun() throws Exception {
370 >                    try {
371 >                        barrier.await();
372 >                        shouldThrow();
373 >                    } catch (BrokenBarrierException success) {}
374 >                }});
375 >            Thread t2 = newStartedThread(new CheckedRunnable() {
376 >                public void realRun() throws Exception {
377 >                    awaitNumberWaiting(barrier, 1);
378 >                    long startTime = System.nanoTime();
379 >                    try {
380 >                        barrier.await(timeoutMillis(), MILLISECONDS);
381 >                        shouldThrow();
382 >                    } catch (TimeoutException success) {}
383 >                    assertTrue(millisElapsedSince(startTime) >= timeoutMillis());
384 >                }});
385 >
386 >            awaitTermination(t1);
387 >            awaitTermination(t2);
388 >            assertEquals(0, barrier.getNumberWaiting());
389 >            assertTrue(barrier.isBroken());
390 >            assertEquals(0, barrier.getNumberWaiting());
391 >            barrier.reset();
392 >            assertFalse(barrier.isBroken());
393 >            assertEquals(0, barrier.getNumberWaiting());
394 >        }
395 >    }
396 >
397 >    /**
398 >     * Reset of a barrier after a failed command reinitializes it.
399 >     */
400 >    public void testResetAfterCommandException() throws Exception {
401 >        final CyclicBarrier barrier =
402 >            new CyclicBarrier(3, new Runnable() {
403 >                    public void run() {
404 >                        throw new NullPointerException(); }});
405 >        for (int i = 0; i < 2; i++) {
406 >            final CyclicBarrier start = new CyclicBarrier(3);
407 >            Thread t1 = new ThreadShouldThrow(BrokenBarrierException.class) {
408 >                public void realRun() throws Exception {
409 >                    start.await();
410 >                    barrier.await();
411 >                }};
412 >
413 >            Thread t2 = new ThreadShouldThrow(BrokenBarrierException.class) {
414 >                public void realRun() throws Exception {
415 >                    start.await();
416 >                    barrier.await();
417 >                }};
418 >
419 >            t1.start();
420 >            t2.start();
421 >            start.await();
422 >            awaitNumberWaiting(barrier, 2);
423 >            try {
424 >                barrier.await();
425 >                shouldThrow();
426 >            } catch (NullPointerException success) {}
427 >            awaitTermination(t1);
428 >            awaitTermination(t2);
429 >            assertTrue(barrier.isBroken());
430 >            assertEquals(0, barrier.getNumberWaiting());
431 >            barrier.reset();
432 >            assertFalse(barrier.isBroken());
433 >            assertEquals(0, barrier.getNumberWaiting());
434          }
435      }
436  
437 +    /**
438 +     * There can be more threads calling await() than parties, as long as each
439 +     * task only calls await once and the task count is a multiple of parties.
440 +     */
441 +    public void testMoreTasksThanParties() throws Exception {
442 +        final ThreadLocalRandom rnd = ThreadLocalRandom.current();
443 +        final int parties = rnd.nextInt(1, 5);
444 +        final int nTasks = rnd.nextInt(1, 5) * parties;
445 +        final AtomicInteger tripCount = new AtomicInteger(0);
446 +        final AtomicInteger awaitCount = new AtomicInteger(0);
447 +        final CyclicBarrier barrier =
448 +            new CyclicBarrier(parties, () -> tripCount.getAndIncrement());
449 +        final ExecutorService e = Executors.newFixedThreadPool(nTasks);
450 +        final Runnable awaiter = () -> {
451 +            try {
452 +                if (randomBoolean())
453 +                    barrier.await();
454 +                else
455 +                    barrier.await(LONG_DELAY_MS, MILLISECONDS);
456 +                awaitCount.getAndIncrement();
457 +            } catch (Throwable fail) { threadUnexpectedException(fail); }};
458 +        try (PoolCleaner cleaner = cleaner(e)) {
459 +            for (int i = nTasks; i--> 0; )
460 +                e.execute(awaiter);
461 +        }
462 +        assertEquals(nTasks / parties, tripCount.get());
463 +        assertEquals(nTasks, awaitCount.get());
464 +        assertEquals(0, barrier.getNumberWaiting());
465 +    }
466   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines