public void testHeavyConcurrentAccess()
	{
		final int MAX = 1 << 20;
		
		// Writers pop from this.
		final AtomicStack<Integer> source = new AtomicStack<Integer>();
		// Writers push to this, Readers pop from this (concurrent action!).
		final AtomicStack<Integer> transfer = new AtomicStack<Integer>();
		// Readers push to this.
		final AtomicStack<Integer> target = new AtomicStack<Integer>();
		
		// Start watch to get reference times
		watch.start();
		
		Runnable writer = new Runnable() {
			public void run() {
				System.out.format("Writer [%d] started at %d\n", Thread.currentThread().getId(), watch.millis());
				int written = 0;
				for (Integer x = source.pop(); x != null; x = source.pop()) {
					transfer.push(x);
					written++;
				}
				System.out.format("Writer [%d] stopped at %d with %d writes\n", Thread.currentThread().getId(), watch.millis(), written);
			}
		};
		
		Runnable reader = new Runnable() {
			public void run() {
				sleep(2);		// start off slower so there are items to pull
				System.out.format("Reader [%d] started at %d\n", Thread.currentThread().getId(), watch.millis());
				int read = 0;
				for (Integer x = transfer.pop(); x != null; x = transfer.pop()) {
					target.push(x);
					read++;
				}
				System.out.format("Reader [%d] stopped at %d with %d reads\n", Thread.currentThread().getId(), watch.millis(), read);
			}
		};
		
		// Fill source
		for (int i = 0; i < MAX; i++) {
			source.push(i);
		}
		
		GroupTask.initialize(6);
		GroupTask.add(writer, 2);
		GroupTask.add(reader, 4);
		GroupTask.execute();
		
		// Check target: sort numbers then check for existence
		List<Integer> result = new ArrayList<Integer>();
		for (Integer x = target.pop(); x != null; x = target.pop()) {
			result.add(x);
		}
		Collections.sort(result);
		
		assertEquals( MAX, result.size() );
		
		for (int i = 0; i < MAX; i++) {
			assertEquals( Integer.valueOf(i), result.get(i) );
		}
	}