| /* |
| * 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. |
| */ |
| |
| import junit.framework.*; |
| import java.util.*; |
| import java.util.concurrent.*; |
| import java.io.*; |
| |
| public class SynchronousQueueTest extends JSR166TestCase { |
| |
| public static void main(String[] args) { |
| junit.textui.TestRunner.run (suite()); |
| } |
| |
| public static Test suite() { |
| return new TestSuite(SynchronousQueueTest.class); |
| } |
| |
| /** |
| * A SynchronousQueue is both empty and full |
| */ |
| public void testEmptyFull() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertTrue(q.isEmpty()); |
| assertEquals(0, q.size()); |
| assertEquals(0, q.remainingCapacity()); |
| assertFalse(q.offer(zero)); |
| } |
| |
| /** |
| * A fair SynchronousQueue is both empty and full |
| */ |
| public void testFairEmptyFull() { |
| SynchronousQueue q = new SynchronousQueue(true); |
| assertTrue(q.isEmpty()); |
| assertEquals(0, q.size()); |
| assertEquals(0, q.remainingCapacity()); |
| assertFalse(q.offer(zero)); |
| } |
| |
| /** |
| * offer(null) throws NPE |
| */ |
| public void testOfferNull() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.offer(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { } |
| } |
| |
| /** |
| * add(null) throws NPE |
| */ |
| public void testAddNull() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.add(null); |
| shouldThrow(); |
| } catch (NullPointerException success) { } |
| } |
| |
| /** |
| * offer fails if no active taker |
| */ |
| public void testOffer() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertFalse(q.offer(one)); |
| } |
| |
| /** |
| * add throws ISE if no active taker |
| */ |
| public void testAdd() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertEquals(0, q.remainingCapacity()); |
| q.add(one); |
| shouldThrow(); |
| } catch (IllegalStateException success){ |
| } |
| } |
| |
| /** |
| * addAll(null) throws NPE |
| */ |
| public void testAddAll1() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.addAll(null); |
| shouldThrow(); |
| } |
| catch (NullPointerException success) {} |
| } |
| |
| /** |
| * addAll(this) throws IAE |
| */ |
| public void testAddAllSelf() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.addAll(q); |
| shouldThrow(); |
| } |
| catch (IllegalArgumentException success) {} |
| } |
| |
| /** |
| * addAll of a collection with null elements throws NPE |
| */ |
| public void testAddAll2() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] ints = new Integer[1]; |
| q.addAll(Arrays.asList(ints)); |
| shouldThrow(); |
| } |
| catch (NullPointerException success) {} |
| } |
| /** |
| * addAll throws ISE if no active taker |
| */ |
| public void testAddAll4() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] ints = new Integer[1]; |
| for (int i = 0; i < 1; ++i) |
| ints[i] = new Integer(i); |
| q.addAll(Arrays.asList(ints)); |
| shouldThrow(); |
| } |
| catch (IllegalStateException success) {} |
| } |
| |
| /** |
| * put(null) throws NPE |
| */ |
| public void testPutNull() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.put(null); |
| shouldThrow(); |
| } |
| catch (NullPointerException success){ |
| } |
| catch (InterruptedException ie) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * put blocks interruptibly if no active taker |
| */ |
| public void testBlockingPut() { |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.put(zero); |
| threadShouldThrow(); |
| } catch (InterruptedException ie){ |
| } |
| }}); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } |
| catch (InterruptedException ie) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * put blocks waiting for take |
| */ |
| public void testPutWithTake() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| int added = 0; |
| try { |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| threadShouldThrow(); |
| } catch (InterruptedException e){ |
| assertTrue(added >= 1); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| q.take(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed offer times out if elements not taken |
| */ |
| public void testTimedOffer() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| |
| threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch (InterruptedException success){} |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SMALL_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * take blocks interruptibly when empty |
| */ |
| public void testTakeFromEmpty() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| q.take(); |
| threadShouldThrow(); |
| } catch (InterruptedException success){ } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * put blocks interruptibly if no active taker |
| */ |
| public void testFairBlockingPut() { |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(true); |
| q.put(zero); |
| threadShouldThrow(); |
| } catch (InterruptedException ie){ |
| } |
| }}); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } |
| catch (InterruptedException ie) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * put blocks waiting for take |
| */ |
| public void testFairPutWithTake() { |
| final SynchronousQueue q = new SynchronousQueue(true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| int added = 0; |
| try { |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| q.put(new Object()); |
| ++added; |
| threadShouldThrow(); |
| } catch (InterruptedException e){ |
| assertTrue(added >= 1); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| q.take(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed offer times out if elements not taken |
| */ |
| public void testFairTimedOffer() { |
| final SynchronousQueue q = new SynchronousQueue(true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| |
| threadAssertFalse(q.offer(new Object(), SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| q.offer(new Object(), LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch (InterruptedException success){} |
| } |
| }); |
| |
| try { |
| t.start(); |
| Thread.sleep(SMALL_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * take blocks interruptibly when empty |
| */ |
| public void testFairTakeFromEmpty() { |
| final SynchronousQueue q = new SynchronousQueue(true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| q.take(); |
| threadShouldThrow(); |
| } catch (InterruptedException success){ } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * poll fails unless active taker |
| */ |
| public void testPoll() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertNull(q.poll()); |
| } |
| |
| /** |
| * timed pool with zero timeout times out if no active taker |
| */ |
| public void testTimedPoll0() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertNull(q.poll(0, TimeUnit.MILLISECONDS)); |
| } catch (InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed pool with nonzero timeout times out if no active taker |
| */ |
| public void testTimedPoll() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| } catch (InterruptedException e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Interrupted timed poll throws InterruptedException instead of |
| * returning timeout status |
| */ |
| public void testInterruptedTimedPoll() { |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| } catch (InterruptedException success){ |
| } |
| }}); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } |
| catch (InterruptedException ie) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed poll before a delayed offer fails; after offer succeeds; |
| * on interruption throws |
| */ |
| public void testTimedPollWithOffer() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch (InterruptedException success) { } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SMALL_DELAY_MS); |
| assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * Interrupted timed poll throws InterruptedException instead of |
| * returning timeout status |
| */ |
| public void testFairInterruptedTimedPoll() { |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(true); |
| assertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| } catch (InterruptedException success){ |
| } |
| }}); |
| t.start(); |
| try { |
| Thread.sleep(SHORT_DELAY_MS); |
| t.interrupt(); |
| t.join(); |
| } |
| catch (InterruptedException ie) { |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * timed poll before a delayed offer fails; after offer succeeds; |
| * on interruption throws |
| */ |
| public void testFairTimedPollWithOffer() { |
| final SynchronousQueue q = new SynchronousQueue(true); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| threadAssertNull(q.poll(SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| q.poll(LONG_DELAY_MS, TimeUnit.MILLISECONDS); |
| threadShouldThrow(); |
| } catch (InterruptedException success) { } |
| } |
| }); |
| try { |
| t.start(); |
| Thread.sleep(SMALL_DELAY_MS); |
| assertTrue(q.offer(zero, SHORT_DELAY_MS, TimeUnit.MILLISECONDS)); |
| t.interrupt(); |
| t.join(); |
| } catch (Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| /** |
| * peek returns null |
| */ |
| public void testPeek() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertNull(q.peek()); |
| } |
| |
| /** |
| * element throws NSEE |
| */ |
| public void testElement() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.element(); |
| shouldThrow(); |
| } |
| catch (NoSuchElementException success) {} |
| } |
| |
| /** |
| * remove throws NSEE if no active taker |
| */ |
| public void testRemove() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.remove(); |
| shouldThrow(); |
| } catch (NoSuchElementException success){ |
| } |
| } |
| |
| /** |
| * remove(x) returns false |
| */ |
| public void testRemoveElement() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertFalse(q.remove(zero)); |
| assertTrue(q.isEmpty()); |
| } |
| |
| /** |
| * contains returns false |
| */ |
| public void testContains() { |
| SynchronousQueue q = new SynchronousQueue(); |
| assertFalse(q.contains(zero)); |
| } |
| |
| /** |
| * clear ensures isEmpty |
| */ |
| public void testClear() { |
| SynchronousQueue q = new SynchronousQueue(); |
| q.clear(); |
| assertTrue(q.isEmpty()); |
| } |
| |
| /** |
| * containsAll returns false unless empty |
| */ |
| public void testContainsAll() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] empty = new Integer[0]; |
| assertTrue(q.containsAll(Arrays.asList(empty))); |
| Integer[] ints = new Integer[1]; ints[0] = zero; |
| assertFalse(q.containsAll(Arrays.asList(ints))); |
| } |
| |
| /** |
| * retainAll returns false |
| */ |
| public void testRetainAll() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] empty = new Integer[0]; |
| assertFalse(q.retainAll(Arrays.asList(empty))); |
| Integer[] ints = new Integer[1]; ints[0] = zero; |
| assertFalse(q.retainAll(Arrays.asList(ints))); |
| } |
| |
| /** |
| * removeAll returns false |
| */ |
| public void testRemoveAll() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] empty = new Integer[0]; |
| assertFalse(q.removeAll(Arrays.asList(empty))); |
| Integer[] ints = new Integer[1]; ints[0] = zero; |
| assertFalse(q.containsAll(Arrays.asList(ints))); |
| } |
| |
| |
| /** |
| * toArray is empty |
| */ |
| public void testToArray() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Object[] o = q.toArray(); |
| assertEquals(o.length, 0); |
| } |
| |
| /** |
| * toArray(a) is nulled at position 0 |
| */ |
| public void testToArray2() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Integer[] ints = new Integer[1]; |
| assertNull(ints[0]); |
| } |
| |
| /** |
| * toArray(null) throws NPE |
| */ |
| public void testToArray_BadArg() { |
| try { |
| SynchronousQueue q = new SynchronousQueue(); |
| Object o[] = q.toArray(null); |
| shouldThrow(); |
| } catch(NullPointerException success){} |
| } |
| |
| |
| /** |
| * iterator does not traverse any elements |
| */ |
| public void testIterator() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Iterator it = q.iterator(); |
| assertFalse(it.hasNext()); |
| try { |
| Object x = it.next(); |
| shouldThrow(); |
| } |
| catch (NoSuchElementException success) {} |
| } |
| |
| /** |
| * iterator remove throws ISE |
| */ |
| public void testIteratorRemove() { |
| SynchronousQueue q = new SynchronousQueue(); |
| Iterator it = q.iterator(); |
| try { |
| it.remove(); |
| shouldThrow(); |
| } |
| catch (IllegalStateException success) {} |
| } |
| |
| /** |
| * toString returns a non-null string |
| */ |
| public void testToString() { |
| SynchronousQueue q = new SynchronousQueue(); |
| String s = q.toString(); |
| assertNotNull(s); |
| } |
| |
| |
| /** |
| * offer transfers elements across Executor tasks |
| */ |
| public void testOfferInExecutor() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| ExecutorService executor = Executors.newFixedThreadPool(2); |
| final Integer one = new Integer(1); |
| |
| executor.execute(new Runnable() { |
| public void run() { |
| threadAssertFalse(q.offer(one)); |
| try { |
| threadAssertTrue(q.offer(one, MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertEquals(0, q.remainingCapacity()); |
| } |
| catch (InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| executor.execute(new Runnable() { |
| public void run() { |
| try { |
| Thread.sleep(SMALL_DELAY_MS); |
| threadAssertEquals(one, q.take()); |
| } |
| catch (InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| joinPool(executor); |
| |
| } |
| |
| /** |
| * poll retrieves elements across Executor threads |
| */ |
| public void testPollInExecutor() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| ExecutorService executor = Executors.newFixedThreadPool(2); |
| executor.execute(new Runnable() { |
| public void run() { |
| threadAssertNull(q.poll()); |
| try { |
| threadAssertTrue(null != q.poll(MEDIUM_DELAY_MS, TimeUnit.MILLISECONDS)); |
| threadAssertTrue(q.isEmpty()); |
| } |
| catch (InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| executor.execute(new Runnable() { |
| public void run() { |
| try { |
| Thread.sleep(SMALL_DELAY_MS); |
| q.put(new Integer(1)); |
| } |
| catch (InterruptedException e) { |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| joinPool(executor); |
| } |
| |
| /** |
| * a deserialized serialized queue is usable |
| */ |
| public void testSerialization() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| ByteArrayOutputStream bout = new ByteArrayOutputStream(10000); |
| ObjectOutputStream out = new ObjectOutputStream(new BufferedOutputStream(bout)); |
| out.writeObject(q); |
| out.close(); |
| |
| ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray()); |
| ObjectInputStream in = new ObjectInputStream(new BufferedInputStream(bin)); |
| SynchronousQueue r = (SynchronousQueue)in.readObject(); |
| assertEquals(q.size(), r.size()); |
| while (!q.isEmpty()) |
| assertEquals(q.remove(), r.remove()); |
| } catch(Exception e){ |
| e.printStackTrace(); |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * drainTo(null) throws NPE |
| */ |
| public void testDrainToNull() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.drainTo(null); |
| shouldThrow(); |
| } catch(NullPointerException success) { |
| } |
| } |
| |
| /** |
| * drainTo(this) throws IAE |
| */ |
| public void testDrainToSelf() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.drainTo(q); |
| shouldThrow(); |
| } catch(IllegalArgumentException success) { |
| } |
| } |
| |
| /** |
| * drainTo(c) of empty queue doesn't transfer elements |
| */ |
| public void testDrainTo() { |
| SynchronousQueue q = new SynchronousQueue(); |
| ArrayList l = new ArrayList(); |
| q.drainTo(l); |
| assertEquals(q.size(), 0); |
| assertEquals(l.size(), 0); |
| } |
| |
| /** |
| * drainTo empties queue, unblocking a waiting put. |
| */ |
| public void testDrainToWithActivePut() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t = new Thread(new Runnable() { |
| public void run() { |
| try { |
| q.put(new Integer(1)); |
| } catch (InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| try { |
| t.start(); |
| ArrayList l = new ArrayList(); |
| Thread.sleep(SHORT_DELAY_MS); |
| q.drainTo(l); |
| assertTrue(l.size() <= 1); |
| if (l.size() > 0) |
| assertEquals(l.get(0), new Integer(1)); |
| t.join(); |
| assertTrue(l.size() <= 1); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| /** |
| * drainTo(null, n) throws NPE |
| */ |
| public void testDrainToNullN() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.drainTo(null, 0); |
| shouldThrow(); |
| } catch(NullPointerException success) { |
| } |
| } |
| |
| /** |
| * drainTo(this, n) throws IAE |
| */ |
| public void testDrainToSelfN() { |
| SynchronousQueue q = new SynchronousQueue(); |
| try { |
| q.drainTo(q, 0); |
| shouldThrow(); |
| } catch(IllegalArgumentException success) { |
| } |
| } |
| |
| /** |
| * drainTo(c, n) empties up to n elements of queue into c |
| */ |
| public void testDrainToN() { |
| final SynchronousQueue q = new SynchronousQueue(); |
| Thread t1 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| q.put(one); |
| } catch (InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| Thread t2 = new Thread(new Runnable() { |
| public void run() { |
| try { |
| q.put(two); |
| } catch (InterruptedException ie){ |
| threadUnexpectedException(); |
| } |
| } |
| }); |
| |
| try { |
| t1.start(); |
| t2.start(); |
| ArrayList l = new ArrayList(); |
| Thread.sleep(SHORT_DELAY_MS); |
| q.drainTo(l, 1); |
| assertTrue(l.size() == 1); |
| q.drainTo(l, 1); |
| assertTrue(l.size() == 2); |
| assertTrue(l.contains(one)); |
| assertTrue(l.contains(two)); |
| t1.join(); |
| t2.join(); |
| } catch(Exception e){ |
| unexpectedException(); |
| } |
| } |
| |
| |
| } |