import java.util.ArrayList; import java.util.List; import java.util.NoSuchElementException; // Helper class for creating True-Iterators. // It uses a producer-consumer synchronization model -- the yield method produces the data // and the get method consumes it. public class IteratorHelper { // True-Iterator (in this example the Range class) thread. Thread t; // List is used as a temporary buffer between the producer (the yield method) and // the consumer (the get method). Though only one element is every stored in this // list, it used for convenience. List list; public IteratorHelper(Runnable r) { t = new Thread(r); list = new ArrayList(); } public void start() { t.start(); } // Store the specified element in the temporary list and notify the done // method.Then it waits for the data to be consumed by the get method // before returning. public void yield(T v) { synchronized (list) { // Produce the data. list.add(v); // This will notify the done() method. list.notify(); } // Wait for the produced data to be consumed. synchronized (list) { try { while (!list.isEmpty()) { list.wait(); } } catch (InterruptedException e) { e.printStackTrace(); } } } // Uses the done() method to wait for the data to be produced by the yield // method. Then consumes the data and notifies the yield method. public T get() { T ret; if (!done()) { synchronized (list) { // Consume the data. ret = list.remove(0); // This will notify the yield method. list.notify(); } } else { throw new NoSuchElementException(); } return ret; } // Waits for the yield method to produce data or the iterator thread to terminate. // If the iterator thread is terminated then the iterator has reached the end. On the // other hand if data is produced by the yield method then this method returns false. public boolean done() { synchronized (list) { // Simulating a "semaphore" to wait for one of the two events -- the Iterator // thread to terminate or yield method to produce data. while (t.isAlive() && list.isEmpty()) { try { list.wait(100); } catch (InterruptedException e) { e.printStackTrace(); } } } // If the yield method produces data it also waits till it is consumed. Hence the // Iterator thread will not be terminated. return !t.isAlive(); } }