1) How can I use a Supplier (supplier) to create a sized stream of N values in parallel, while ensuring that no more than N calls are made to the supplier? I need this because I have a supplier with a costly supplier.get() operation.
2) The 'obvious' answer to my question, Streams.generate(supplier).limit(N), does not work and often results in more than N calls being made to the supplier. Why is this?
As 'proof' of the fact that Streams.generate(supplier).limit(N) results in more than N calls to supplier.get(), consider the following code:
public class MWE {
    static final int N_ELEMENTS=100000;
    static Supplier<IntSupplier> mySupplier = () -> new IntSupplier() {
        AtomicInteger ai = new AtomicInteger(-1);
        @Override
        public int getAsInt() {
            return ai.incrementAndGet();
        }
    };
    public static void main(String[] args) {
        int[] a = IntStream.generate(mySupplier.get()).limit(N_ELEMENTS).toArray();
        int[] b = IntStream.generate(mySupplier.get()).parallel().limit(N_ELEMENTS).toArray();
    }
}
a is equal to [0, 1, ..., N_ELEMENTS-1] as expected, but contrary to what you might expect b does not contain the same elements as a. Instead, b often contains elements that are greater than or equal to N_ELEMENTS, which indicates more than N_ELEMENTS number of calls to the supplier.
Another illustration would be that Streams.generate(new Random(0)::nextDouble()).limit(5) does not always generate the same set of numbers.
 
     
    