package com.hypirion.primes;

import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;

public final class Primes implements Iterable<Integer>{
    private static ArrayList<Integer> primeList = new ArrayList<Integer>
        (Arrays.asList(new Integer[]{2, 3, 5, 7, 11}));

    public static List<Integer> takeUnder(int n){
        createAllUnder(n);
        int i = Collections.binarySearch(primeList, n);
        if (i < 0)
            i = ~i;
        return take(i);
    }

    public static List<Integer> take(int n){
        ensureExists(n);
        return Collections.unmodifiableList(primeList.subList(0, n));
    }

    public static int get(int n){
        ensureExists(n);
        return primeList.get(n);
    }

    public static boolean isPrime(long n){
        if (n == 1)
            return false;

        int sqrt = (int) Math.sqrt(n);
        createAllUnder(sqrt+1);

        for (int prime : primeList){
            if (sqrt < prime)
                break;
            else if (n % prime == 0)
                return false;
        }

        return true;
    }

    private static void ensureExists(int n){
        for (int i = primeList.size(); i <= n; i++)
            addPrime();
    }

    private static void createAllUnder(int n){
        while (primeList.get(primeList.size() -1) < n)
            addPrime();
    }

    private static void addPrime(){
        int possiblePrime = primeList.get(primeList.size() - 1);

        do possiblePrime += relativeNext();
        while (!isPrime(possiblePrime));

        primeList.add(possiblePrime);
    }

    private static final int[] wheel = {2, 4, 2, 4, 6, 2, 6, 4, 2, 4, 6,
                                        6, 2, 6, 4, 2, 6, 4, 6, 8, 4, 2,
                                        4, 2, 4, 8, 6, 4, 6, 2, 4, 6, 2,
                                        6, 6, 4, 2, 4, 6, 2, 6, 4, 2, 4,
                                        2, 10, 2, 10};

    private static int pos = 0;

    private static int relativeNext(){
        int n = wheel[pos];
        pos++;
        if (pos == wheel.length)
            pos = 0;
        return n;
    }

    public static void clear(){
        primeList = new ArrayList<Integer>(Arrays.asList
                                           (new Integer[]{2, 3, 5, 7, 11}));
        pos = 0;
    }

    private Primes(){}
    public static final Primes PRIME = new Primes();

    public Iterator<Integer> iterator(){
        return new PrimeIter();
    }

    private static class PrimeIter implements Iterator<Integer> {
        private int pos, atLeast;

        public PrimeIter(){
            pos = 0;
            atLeast = primeList.size();
        }

        @Override
        public boolean hasNext(){
            return true;
        }

        @Override
        public Integer next(){
            if (pos < atLeast){
                return primeList.get(pos++);
            }
            addPrime();
            atLeast = primeList.size();
            return next();
        }

        @Override
        public void remove(){
            throw new UnsupportedOperationException
                ("Can't remove primes from a prime list");
        }
    }
}

@@ -155,16 +155,65 @@
 terator;
+%0Aimport java.util.concurrent.locks.ReentrantLock;
 %0A%0Apublic
@@ -281,16 +281,25 @@
  static 
+volatile 
 ArrayLis
@@ -312,32 +312,40 @@
 ger%3E primeList =
+%0A       
  new ArrayList%3CI
@@ -351,25 +351,16 @@
 Integer%3E
-%0A        
 (Arrays.
@@ -396,24 +396,92 @@
  7, 11%7D));%0A%0A
+    private static final ReentrantLock lock = new ReentrantLock();%0A%0A
     public s
@@ -1568,24 +1568,63 @@
 addPrime()%7B%0A
+        lock.lock();%0A        try %7B%0A    
         int 
@@ -1685,16 +1685,20 @@
         
+    
 do possi
@@ -1729,24 +1729,28 @@
 ();%0A        
+ 
+   
 while (!isPr
@@ -1767,24 +1767,28 @@
 lePrime));%0A%0A
+    
         prim
@@ -1813,16 +1813,81 @@
 Prime);%0A
+        %7D%0A        finally %7B%0A            lock.unlock();%0A        %7D%0A
     %7D%0A%0A 

Make Primes safe to use concurrently.