
import java.util.ArrayList;

import java.io.*;


// Beispiel vom 14.11.2014
// in Thread08 sind getSumme und decSumme fehlerhaft
// man darf nur eine Methode benutzen
// Methode  gibt einen Wert UND definiert das Ende der Schleife


public class Thread_Primzahlen  {

   private static void pause() {
    try {
      System.in.read();
    }
    catch (IOException e) {
    }
  }  // pause


     private final int MAX = 300000;  // 200000

     private final int AnzThread = 8;

     // ein Thread
	private void test1() {      
      Thread1 cpu;
      int i;
      long t1, t2;
      int [] zahlen;
      zahlen = new int[MAX-1];
      for (i=2; i<=MAX; i++) 
         zahlen[i-2]=i;
      cpu = new Thread1(zahlen);
      System.out.println("Start von test1 (ein Thread)\n" );
      t1 =  System.currentTimeMillis();
      cpu.start();
      	try {
   		cpu.join();
      }
      catch (InterruptedException e) {
      }
      t2 =  System.currentTimeMillis();
      System.out.println((t2-t1)+" ms" );
      // frame.setVisible(false);
  	}

     // 4 Thread
	private void test2() {      
      Thread [] cpus;
      int i,j, d1, d2, diff;
      long t1, t2;
      int [] zahlen;
      cpus = new Thread[AnzThread];
      diff = MAX / AnzThread;
      d1=2;  // untere Grenz
      d2=diff; // obere Grenze
      for (i=0; i<AnzThread; i++) {
        if (d2>MAX) d2=MAX;
        zahlen = new int[d2-d1+1];
        for (j=d1; j<=d2; j++) 
           zahlen[j-d1]=j;
        cpus[i] = new Thread1(zahlen);
        d1+=diff;
        d2+=diff;
      }
  
      System.out.println("\n\nStart von test2 ("+AnzThread+" Thread)\n" );
      t1 =  System.currentTimeMillis();
      for (i=0; i<AnzThread; i++) {
        cpus[i].start();
      }
      try {
        for (i=0; i<AnzThread; i++) {
          cpus[i].join();
        }
      }
      catch (InterruptedException e) {
      }
      t2 =  System.currentTimeMillis();
      System.out.println((t2-t1)+" ms" );
   }

     // 4 Thread
   private void test3() {      
      Thread [] cpus;
      long t1, t2;
      int i;
      cpus = new Thread[AnzThread];
  
      CMaster master = CMaster.getInstance();
      master.setPakete(MAX);
  
      for (i=0; i<AnzThread; i++) {
        cpus[i] = new Thread2();
      }
  
      System.out.println("\n\nStart von test3: Paketverwaltung ("+AnzThread+" Thread)\n" );
      t1 =  System.currentTimeMillis();
      for (i=0; i<AnzThread; i++) {
        cpus[i].start();
      }
      	try {
        for (i=0; i<AnzThread; i++) {
          cpus[i].join();
        }
      }
      catch (InterruptedException e) {
      }
      t2 =  System.currentTimeMillis();
        System.out.println((t2-t1)+" ms" );
   }


  public static void main(String[] args) {
    Thread_Primzahlen frame = new Thread_Primzahlen();
    // frame.test1();
    frame.test2();
    frame.test3();
    pause();
  }
  
}


class Thread1 extends Thread {
  int [] _zahlen;

  public Thread1(int [] zahlen) {
    _zahlen = zahlen;
  } // myThread1


  public void run() {
    String sErg="";
    boolean bPrim;
    int j;
    if (_zahlen!=null) {
      for (int z : _zahlen) {
        bPrim=true;
        for (j=2; j<z; j++) {
          if ( (z%j)==0) {
            bPrim=false;
            break;
          }
        } // for
        if (bPrim) sErg+=z+"\n";
      } // for (int z : zahlen) {
    }
    System.out.println("Ende");
  }  // run

}  // Thread1



class Thread2 extends Thread {
  int [] _zahlen;

  public Thread2() {
    _zahlen = null;
  } // myThread2


  public void run() {
    String sErg="";
    boolean bPrim;
    int j;
       CMaster master = CMaster.getInstance();
       int [] zahlen;
       while (true) {
         zahlen = master.getPaket();
         if (zahlen==null) break;
         for (int z : zahlen) {
           bPrim=true;
           for (j=2; j<z; j++) {
             if ( (z%j)==0) {
               bPrim=false;
               break;
             }
           } // for
           if (bPrim) sErg+=z+"\n";
         } // for (int z : zahlen) {
       }  // while
    // System.out.println(sErg);
    System.out.println("Ende");
  }  // run

}  // Thread2



class CMaster {
  private final int STEP = 100;
  private static CMaster _instance = new CMaster();
  private ArrayList _liste;
  private int _index;

  private CMaster() {
     _liste= new ArrayList();
  }

  public static CMaster getInstance() {
   return _instance;
  }

  public synchronized  int [] getPaket() {
    _index++;
    if (_index>=_liste.size())
     return null;
    else
     return (int []) _liste.get(_index);
  }

  public void setPakete(int anz) {
    int j, d1, d2;
    int [] zahlen;
    d1=0;
    d2=STEP;
    _liste.clear();
    while (d1<=anz) {
      if (d2>anz) d2=anz;
      zahlen = new int[d2-d1+1];
      for (j=d1; j<=d2; j++) 
         zahlen[j-d1]=j;
      _liste.add(zahlen);
      d1+=STEP;
      d2+=STEP;
    }  // while    
    _index=-1;
    // System.out.println("Count: "+_liste.size() );
  }

}