Multi-Threaded Java Based Prime Number Generator - java

I am working on a prime number generator that is multi-threaded. My goal for this multi-threaded process is that each process will check a single number. I do have somewhat working code, but I am having some issues with the "locking" concept in where the schedular is running 2 process's very closely to each other.
Claimed Lock: 0; Claimed Number: 75827; isPrime: false
Claimed Lock: 1; Claimed Number: 75829; isPrime: false
Claimed Lock: 2; Claimed Number: 75831; isPrime: false
Claimed Lock: 4; Claimed Number: 75835; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 5; Claimed Number: 75837; isPrime: false
Claimed Lock: 3; Claimed Number: 75833; isPrime: true
Claimed Lock: 6; Claimed Number: 75839; isPrime: false.
(you can see that 2 locks - i.e. 5 get called twice - they should be disctinct)
My main goal of this program is to have 1 thread calculate 1 based prime numbers. There will be n number of threads based on what Java JVM reports back to the int cores variable inside of the code.
Here is a quick explanation of my program:
The program starts out getting the number logical cpu cores of the given computer
Creates a 2d Array of [2] [Num of CPU Cores]
Array[0][i] = Gets filled with 2k+1 (odd numbers) of potential prime numbers (doing this since 2 is the only known prime number that is even)
Array[1][i] = Gets filled with "-1" = Meaning that number is ready to be picked up by a process/thread
The program then spins up n number of threads (based on cpu core count)
A new thread that has been created is supposed to look for the next available Array[1][i] == -1 and change it to the value of 2. (2 represents a process lock and/or the number is being checked if prime or not)
-6a. The n number of child processes check if prime, and will change the Array[1][i] to either 1 or 0 (1 meaning it is prime or 0 meaning its not prime)
-6b. Child Process Terminates
Parent process - Main will busy wait until all Array[1][i] is either 1 or 0
Repeat back to step 3
What am I a missing or doing wrong with this logic? I believe I am missing something with the JVM/OS Schedular. But, I feel like I could be incorrect in this assumption as well? What could I do to remedy this issue?
Here is my Code:
Multi-Threaded Class
class MultithreadCalculate extends Thread {
public void run() {
try {
int indexNum = -1;
for (int i = 0; i < MultiThreadPrimeNumGen.cores; i++) {
if (MultiThreadPrimeNumGen.primeArray[1][i] == -1) {
MultiThreadPrimeNumGen.primeArray[1][i] = 2;
indexNum = i;
break;
}
}
boolean isPrime = true;
for (int i = 2; i < MultiThreadPrimeNumGen.primeArray[0][indexNum]; i++) {
if (MultiThreadPrimeNumGen.primeArray[0][indexNum] % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[1][indexNum] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Claimed Lock: " + indexNum + "; Claimed Number: " + MultiThreadPrimeNumGen.primeArray[0][indexNum] + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is the main class:
public class MultiThreadPrimeNumGen {
public static int[][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeBase += 2;
primeArray[0][i] = primeBase;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
//Gets number of CPU Cores
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println("PrimeNum: " + primeArray[0][i]);
out.flush();
}
}
}
}
}

So you want thread at the loop while filling the array:
Runnable run1 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread1 = new Thread(run1);
thread1.start();
Runnable run2 = new Runnable(){
public void run()
{
// Code to fill array
}
};
Thread thread2 = new Thread2(run2);
thread2.start();

Actually, I solved my own idea without using Locks. The Idea Came from another user who posted on here: Prime Balpreet. So thank you! What I did was create getters and setters inside of the code. Here is the Modified code:
Multithreaded Class:
class MultithreadCalculate extends Thread {
int PrimeNumCalculate = -1;
int indexNum = -1;
public int getPrimeNumCalculate() {
return PrimeNumCalculate;
}
public void setPrimeNumCalculate(int primeNumCalculate) {
PrimeNumCalculate = primeNumCalculate;
}
public int getIndexNum() {
return indexNum;
}
public void setIndexNum(int indexNum) {
this.indexNum = indexNum;
}
public void run() {
try {
boolean isPrime = true;
for (int i = 2; i < getPrimeNumCalculate(); i++) {
if (getPrimeNumCalculate() % i == 0) {
isPrime = false;
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 0;
break;
}
}
if (isPrime) {
MultiThreadPrimeNumGen.primeArray[0][getIndexNum()] = getPrimeNumCalculate();
MultiThreadPrimeNumGen.primeArray[1][getIndexNum()] = 1;
}
System.out.println("Thread " + Thread.currentThread().getId() + "; Index: " + getIndexNum() + "; Number: " + getPrimeNumCalculate() + "; isPrime: " + isPrime);
}
catch (Exception e) {
System.out.println("Exception is caught");
}
}
}
Here is my Main Class:
public class MultiThreadPrimeNumGen {
public static int [][] primeArray;
public static int primeBase = 1;
public static int cores;
private static void fillArray() {
for (int i = 0; i < cores; i++) {
primeArray[0][i] = -1;
}
for (int i = 0; i < cores; i++) {
primeArray[1][i] = -1;
}
}
public static void main(String[] args) throws FileNotFoundException {
File file = new File(System.getProperty("user.home") + "/Desktop" + "/PrimeNumber.txt");
PrintWriter out = new PrintWriter(file);
cores = Runtime.getRuntime().availableProcessors();
System.out.println("Number of Cores: " + cores);
out.println(2);
out.flush();
while (true) {
primeArray = new int[2][cores];
fillArray();
for (int i = 0; i < cores; i++) {
MultithreadCalculate multithreadCalculate = new MultithreadCalculate();
multithreadCalculate.setPrimeNumCalculate(primeBase += 2);
multithreadCalculate.setIndexNum(i);
multithreadCalculate.start();
}
while (true) {
boolean flag = false;
for (int i = 0; i < cores; i++) {
if ((primeArray[1][i] == 0) || (primeArray[1][i] == 1)) {
flag = true;
} else {
flag = false;
break;
}
}
if (flag) {
break;
}
}
printMatrix(primeArray);
for (int i = 0; i < cores; i++) {
if (primeArray[1][i] == 1) {
out.println(primeArray[0][i]);
}
}
out.flush();
}
}
public static void printMatrix(int[][] arr) {
if (null == arr || arr.length == 0) {
return;
}
int idx = -1;
StringBuilder[] sbArr = new StringBuilder[arr.length];
for (int[] row : arr) {
sbArr[++idx] = new StringBuilder("[\t");
for (int elem : row) {
sbArr[idx].append(elem).append("\t");
}
sbArr[idx].append("]");
}
for (StringBuilder stringBuilder : sbArr) {
System.out.println(stringBuilder);
}
}
}

Related

How to interrupt a method after specific time in Java?

I need to write a simple program that prints prime numbers up to the given number but no longer than 5 seconds.
Is there some kind of timer to use to interrupt a method after a period of time? (but no interruption if printing is shorter than 5 sec).
Thanks in advance.
My code:
public class Primes {
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n; i++) if (checkIfPrime(i)) System.out.println(i);
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
printPrimesAndOperationTime(n);
}
}
Used Java Concurrency APIs to solve the above problem. please find inline comments for code walk through.
import java.util.Scanner;
import java.util.concurrent.*;
public class TimeoutInterval {
public static void main(String[] args) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor(); // Start Single thread executor
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
Future future = executor.submit(new Primes(n)); // Find prime no.
try {
future.get(5, TimeUnit.SECONDS); // Set the time out of the prime no. search task
executor.shutdown();
} catch (TimeoutException e) {
executor.shutdown();
System.out.println("Terminated!");
}
executor.shutdownNow();
}
}
class Primes implements Runnable {
private final int number;
Primes(int number) {
this.number = number;
}
#Override
public void run() {
System.out.println("Started..");
printPrimesAndOperationTime(number);
System.out.println("Finished!");
}
private static boolean checkIfPrime(int x) {
if (x == 2) return true;
if (x % 2 == 0) return false;
int sqrt = (int) Math.sqrt(x) + 1;
for (int i = 3; i < sqrt; i = i + 2) if (x % i == 0) return false;
return true;
}
private static void printPrimesAndOperationTime(int n) {
long start = System.nanoTime();
for (int i = 2; i <= n && !Thread.interrupted(); i++) if (checkIfPrime(i)) {
System.out.println(i);
}
long end = System.nanoTime();
long timeResult = end - start;
System.out.println("Printing time = " + timeResult + " [ns] => "
+ Math.round(timeResult * 100.0 / 1000000) / 100.0 + " [ms]");
}
}
Using ExecutorService, you can submit a task with a timeout. On Receiving the TimeoutException, you should call cancel(true) method on the task to interrupt the thread.
From the documentation
... If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

Barrier Synchronization (Output, increment and wait)

I want to make synchronized threads wait for each other. In the example program, each thread simply counts up to 100. I want the threads to wait every 10 outputs.
Because I am preparing for an exam, I would like to use the CyclicBarrier method.
Here is the code:
public class NumberRunner extends Thread {
private int number;
private CyclicBarrier barrier;
public NumberRunner(int n, CyclicBarrier b) {
number = n;
barrier = b;
}
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("Thread " + number + ": " + i);
}
}
and the Main-Class
public class Barriers {
private final static int NUMBER = 3;
public static void main(String[] args) {
CyclicBarrier barrier = new CyclicBarrier(3);
NumberRunner[] runner = new NumberRunner[NUMBER];
for (int i = 0; i < NUMBER; i++) {
runner[i] = new NumberRunner(i, barrier);
}
for (int i = 0; i < NUMBER; i++) {
runner[i].start();
}
}
How do I insert the barriers?
for (int i = 0; i < 100; i++) {
System.out.println("Thread " + number + ": " + i);
if ((i + 1) % 10 == 0) {
try {
barrier.await();
} catch () {}//whatever exceptions b.await() throws
}
}

Prime factorization using GUI (swing/awt)

This code uses Swing and awt to compute prime factorization, the code works, but it shows only one prime factor, for example: if i compute 56 the answer is just 7, how can i fix it?
thanks in advance
calculate6.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// Get values from text fields
try {
int a = Integer.parseInt(input1.getText());
result.setText(String.valueOf(a + " "));
for (int i = 2; i <= a; i++) {
while (a % i == 0) {
result.setText(String.valueOf(i + " "));
// System.out.println(i + " ");
a = a / i;
}
}
if (a < 1)
result.setText(String.valueOf(a + " "));
// System.out.println(a + " ");
}
catch (Exception f) {
JOptionPane.showMessageDialog(rootPane, "ERROR: " + (f.getMessage()));
}
String aField = input1.getText();
if (e.getSource() == calculate6) {
if ("".equals(aField)) {
String emptyFieldWarning;
emptyFieldWarning = "One field is empty!";
JOptionPane.showMessageDialog(rootPane, emptyFieldWarning);
}
}
}
});
Edit 1: i have changed the operation part
Your Swing part is fine. If you just try to execute
int a = 56;
for(int i = 2; i< a; i++) {
while (a % i == 0) {
a = a / i;
}
}
System.out.println(a);
you get 7,so the problem is in this part, you shoul look over here
Problem is in the while loop. It is not accumulating the factors. Try this getPrimeFactors() in this sample program.
import java.util.*;
public class PrimeFactors {
public static void main(String[] args) {
System.out.println("56 -> " + PrimeFactors.getPrimeFactors(56));
System.out.println("30 -> " + PrimeFactors.getPrimeFactors(30));
System.out.println("154 -> " + PrimeFactors.getPrimeFactors(154));
}
public static List<Integer> getPrimeFactors(int input) {
List<Integer> factors = new ArrayList<>();
for (int i = 2; i <= input; i++) {
while (input%i == 0) {
input = input/i;
factors.add(i);
}
}
return factors;
}
}
public static final IntFunction<String> getPrimeFactorsAsString = num -> {
List<Integer> res = new ArrayList<>();
for (int i = 2, sqrt = (int)Math.sqrt(num); i <= sqrt; i++) {
while (num % i == 0) {
res.add(i);
num /= i;
}
}
return res.stream().map(String::valueOf).collect(Collectors.joining(" "));
};
Demo
System.out.println(getPrimeFactorsAsString.apply(56)); // 2 2 2 7
System.out.println(getPrimeFactorsAsString.apply(660)); // 2 2 3 5 11

Round Robin Scheduler

I need to implement a "round-robin" scheduler with a job class that I cannot modify. Round-robin scheduler should process the job that has been waiting the longest first, then reset timer to zero. If two jobs have same wait time, lower id is processed first. The job class only gives three values (job id, remaining duration, and priority(which is not needed for this). each job has a start time, so only a couple of jobs may be available during first cycle, few more next cycle, etc. Since the "job array" I am calling is different every time I call it, I'm not sure how to store the wait times.
This is the job class:
public class Jobs{
private int[] stas = new int[0];
private int[] durs = new int[0];
private int[] lefs = new int[0];
private int[] pris = new int[0];
private int[] fins = new int[0];
private int clock;
public Jobs()
{
this("joblist.csv");
}
public Jobs(String filename)
{
BufferedReader fp = null;
String line = "";
String[] b = null;
int[] tmp;
try
{
fp = new BufferedReader(new FileReader(filename));
while((line = fp.readLine()) != null)
{
b = line.split(",");
if(b.length == 3)
{
try
{
int sta = Integer.parseInt(b[0]);
//System.out.println("sta: " + b[0]);
int dur = Integer.parseInt(b[1]);
//System.out.println("dur: " + b[1]);
int pri = Integer.parseInt(b[2]);
//System.out.println("pri: " + b[2]);
stas = app(stas, sta);
//System.out.println("stas: " + Arrays.toString(stas));
durs = app(durs, dur);
//System.out.println("durs: " + Arrays.toString(durs));
lefs = app(lefs, dur);
//System.out.println("lefs: " + Arrays.toString(lefs));
pris = app(pris, pri);
//System.out.println("pris: " + Arrays.toString(pris));
fins = app(fins, -1);
//System.out.println("fins: " + Arrays.toString(fins));
}
catch(NumberFormatException e) {}
}
}
fp.close();
}
catch(FileNotFoundException e) { e.printStackTrace(); }
catch(IOException e) { e.printStackTrace(); }
clock = 0;
}
public boolean done()
{
boolean done = true;
for(int i=0; done && i<lefs.length; i++)
if(lefs[i]>0) done=false;
return done;
}
public int getClock() { return clock; }
public int[][] getJobs()
{
int count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
count++;
int[][] jobs = new int[count][3];
count = 0;
for(int i=0; i<stas.length; i++)
if(stas[i]<=clock && lefs[i]>0)
{
jobs[count] = new int[]{i, lefs[i], pris[i]};
count++;
}
return jobs;
}
public int cycle() { return cycle(-1); }
public int cycle(int j)
{
if(j>=0 && j<lefs.length && clock>=stas[j] && lefs[j]>0)
{
lefs[j]--;
if(lefs[j] == 0) fins[j] = clock+1;
}
clock++;
return clock;
}
private int[] app(int[] a, int b)
{
int[] tmp = new int[a.length+1];
for(int i=0; i<a.length; i++) tmp[i] = a[i];
tmp[a.length] = b;
return tmp;
}
public String report()
{
String r = "JOB,PRIORITY,START,DURATION,FINISH,DELAY,PRI*DELAY\n";
float dn=0;
float pdn=0;
for(int i=0; i<stas.length; i++)
{
if(fins[i]>=0)
{
int delay = ((fins[i]-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
else
{
int delay = ((clock*10-stas[i])-durs[i]);
r+= ""+i+","+pris[i]+","+stas[i]+","+durs[i]+","+fins[i]+","+delay+","+(pris[i]*delay)+"\n";
dn+= delay;
pdn+= pris[i]*delay;
}
}
if(stas.length>0)
{
r+= "Avg,,,,,"+(dn/stas.length)+","+pdn/stas.length+"\n";
}
return r;
}
public String toString()
{
String r = "There are "+stas.length+" jobs:\n";
for(int i=0; i<stas.length; i++)
{
r+= " JOB "+i+": START="+stas[i]+" DURATION="+durs[i]+" DURATION_LEFT="+lefs[i]+" PRIORITY="+pris[i]+"\n";
}
return r;
}
I don't need full code, just an idea of how to store wait times and cycle the correct job.
While a array based solution 'may' work, I would advocate a more object oriented approach. Create 'Job' class with the desire attributes (id, start_time, wait etc). Using the csv file, create Job objects and hold them in a list. Write a comparator to sort this jobs-list (in this case based on job wait/age would be the factor).
The job executor then has to do the following:
while(jobs exist) {
iterate on the list {
if job is executable // start_time > current sys_time
consume cycles/job for executable jobs
mark completed jobs (optional)
}
remove the completed jobs
}
//\ This loop will add +1 to each job
for(int i = 0; i < jobs.length; i++)
{
waitTime[jobs[i][0]] += 1;
}
int longestWait = 0;//\ This holds value for greatest wait time
int nextJob = 0; //\ This holds value for index of job with greatest wait time
//\ this loop will check for the greatest wait time and and set variables accordingly
for(int i = 0; i < waitTime.length; i++)
{
if(waitTime[i] > longestWait)
{
longestWait = waitTime[i];
nextJob = i;
}
}
//\ this cycles the job with the highest wait time
jobsource.cycle(nextJob);
//\ this resets the wait time for processed job
waitTime[nextJob] = 0;

Why do object arrays in my ArrayList fail to retain their values?

I am creating a program in Java to simulate evolution. The way I have it set up, each generation is composed of an array of Organism objects. Each of these arrays is an element in the ArrayList orgGenerations. Each generation, of which there could be any amount before all animals die, can have any amount of Organism objects.
For some reason, in my main loop when the generations are going by, I can have this code without errors, where allOrgs is the Organism array of the current generation and generationNumber is the number generations since the first.
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(generationNumber));
printOrgs is a method to display an Organism array, where speed and strength are Organism Field variables:
public void printOrgs(Organism[] list)
{
for (int x=0; x<list.length; x++)
{
System.out.println ("For organism number: " + x + ", speed is: " + list[x].speed + ", and strength is " + list[x].strength + ".");
}
}
Later on, after this loop, when I am trying to retrieve the data to display, I call this very similar code:
printOrgs(orgGenerations.get(0));
This, and every other array in orgGenerations, return a null pointer exception on the print line of the for loop. Why are the Organism objects loosing their values?
Alright, here is all of the code from my main Simulation class. I admit, it might be sort of a mess. The parts that matter are the start and simulator methods. The battle ones are not really applicable to this problem. I think.
import java.awt.FlowLayout;
import java.util.*;
import javax.swing.JFrame;
public class Simulator {
//variables for general keeping track
static Organism[] allOrgs;
static ArrayList<Organism[]> orgGenerations = new ArrayList <Organism[]>();
ArrayList<Integer> battleList = new ArrayList<Integer>();
int deathCount;
boolean done;
boolean runOnce;
//setup
Simulator()
{
done = false;
Scanner asker = new Scanner(System.in);
System.out.println("Input number of organisms for the simulation: ");
int numOfOrgs = asker.nextInt();
asker.close();
Organism[] orgArray = new Organism[numOfOrgs];
for (int i=0; i<numOfOrgs; i++)
{
orgArray[i] = new Organism();
}
allOrgs = orgArray;
}
//graphsOrgs
public void graphOrgs() throws InterruptedException
{
JFrame f = new JFrame("Evolution");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setSize(1000,500);
f.setVisible(true);
Drawer bars = new Drawer();
//System.out.println(orgGenerations.size());
for (int iterator=0;iterator<(orgGenerations.size()-1); iterator++)
{
printOrgs(orgGenerations.get(0));
//The 0 can be any number, no matter what I do it wont work
//System.out.println("first");
f.repaint();
bars.data = orgGenerations.get(iterator);
f.add(bars);
//System.out.println("before");
Thread.sleep(1000);
//System.out.println("end");
}
}
//prints all Orgs and their statistics
public void printOrgs(Organism[] list)
{
System.out.println("Number Of Organisms: " + list.length);
for (int x=0; x<list.length; x++)
{
System.out.println ("For organism number: " + x + ", speed is: " + list[x].speed + ", and strength is " + list[x].strength + ".");
}
System.out.println();
}
//general loop for the organisms lives
public void start(int reproductionTime) throws InterruptedException
{
int generationNumber = 0;
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(0));
generationNumber++;
while(true)
{
deathCount = 0;
for(int j=0; j<reproductionTime; j++)
{
battleList.clear();
for(int m=0; m<allOrgs.length; m++)
{
if (allOrgs[m].alive == true)
oneYearBattleCheck(m);
}
battle();
}
reproduction();
if (done == true)
break;
orgGenerations.add(allOrgs);
printOrgs(orgGenerations.get(generationNumber));
generationNumber++;
}
printOrgs(orgGenerations.get(2));
}
//Checks if they have to fight this year
private void oneYearBattleCheck(int m)
{
Random chaos = new Random();
int speedMod = chaos.nextInt(((int)Math.ceil(allOrgs[m].speed/5.0))+1);
int speedSign = chaos.nextInt(2);
if (speedSign == 0)
speedSign--;
speedMod *= speedSign;
int speed = speedMod + allOrgs[m].speed;
if (speed <= 0)
speed=1;
Random encounter = new Random();
boolean battle = false;
int try1 =(encounter.nextInt(speed));
int try2 =(encounter.nextInt(speed));
int try3 =(encounter.nextInt(speed));
int try4 =(encounter.nextInt(speed));
if (try1 == 0 || try2 == 0 || try3 == 0 || try4 == 0 )
{
battle = true;
}
if(battle == true)
{
battleList.add(m);
}
}
//Creates the matches and runs the battle
private void battle()
{
Random rand = new Random();
if (battleList.size()%2 == 1)
{
int luckyDuck = rand.nextInt(battleList.size());
battleList.remove(luckyDuck);
}
for(int k=0; k<(battleList.size()-1);)
{
int competitor1 = rand.nextInt(battleList.size());
battleList.remove(competitor1);
int competitor2 = rand.nextInt(battleList.size());
battleList.remove(competitor2);
//Competitor 1 strength
int strengthMod = rand.nextInt(((int)Math.ceil(allOrgs[competitor1].strength/5.0))+1);
int strengthSign = rand.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
int comp1Strength = strengthMod + allOrgs[competitor1].strength;
//Competitor 2 strength
strengthMod = rand.nextInt(((int)Math.ceil(allOrgs[competitor2].strength/5.0))+1);
strengthSign = rand.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
int comp2Strength = strengthMod + allOrgs[competitor2].strength;
//Fight!
if (comp1Strength>comp2Strength)
{
allOrgs[competitor1].life ++;
allOrgs[competitor2].life --;
}
else if (comp2Strength>comp1Strength)
{
allOrgs[competitor2].life ++;
allOrgs[competitor1].life --;
}
if (allOrgs[competitor1].life == 0)
{
allOrgs[competitor1].alive = false;
deathCount++;
}
if (allOrgs[competitor2].life == 0)
{
allOrgs[competitor2].alive = false;
deathCount ++ ;
}
}
}
//New organisms
private void reproduction()
{
//System.out.println("Number of deaths: " + deathCount + "\n");
if (deathCount>=(allOrgs.length-2))
{
done = true;
return;
}
ArrayList<Organism> tempOrgs = new ArrayList<Organism>();
Random chooser = new Random();
int count = 0;
while(true)
{
int partner1 = 0;
int partner2 = 0;
boolean partnerIsAlive = false;
boolean unluckyDuck = false;
//choose partner1
while (partnerIsAlive == false)
{
partner1 = chooser.nextInt(allOrgs.length);
if (allOrgs[partner1] != null)
{
if (allOrgs[partner1].alive == true)
{
partnerIsAlive = true;
}
}
}
count++;
//System.out.println("Count 2: " + count);
partnerIsAlive = false;
//choose partner2
while (partnerIsAlive == false)
{
if (count+deathCount == (allOrgs.length))
{
unluckyDuck=true;
break;
}
partner2 = chooser.nextInt(allOrgs.length);
if (allOrgs[partner2] != null)
{
if (allOrgs[partner2].alive == true)
{
partnerIsAlive = true;
}
}
}
if (unluckyDuck == false)
count++;
//System.out.println("count 2: " + count);
if (unluckyDuck == false)
{
int numOfChildren = (chooser.nextInt(4)+1);
for (int d=0; d<numOfChildren; d++)
{
tempOrgs.add(new Organism(allOrgs[partner1].speed, allOrgs[partner2].speed, allOrgs[partner1].strength, allOrgs[partner2].strength ));
}
allOrgs[partner1] = null;
allOrgs[partner2] = null;
}
if (count+deathCount == (allOrgs.length))
{
Arrays.fill(allOrgs, null);
allOrgs = tempOrgs.toArray(new Organism[tempOrgs.size()-1]);
break;
}
//System.out.println(count);
}
}
}
Main method:
public class Runner {
public static void main(String[] args) throws InterruptedException {
Simulator sim = new Simulator();
int lifeSpan = 20;
sim.start(lifeSpan);
sim.graphOrgs();
}
}
Organism class:
import java.util.Random;
public class Organism {
static Random traitGenerator = new Random();
int life;
int speed;
int strength;
boolean alive;
Organism()
{
speed = (traitGenerator.nextInt(49)+1);
strength = (50-speed);
life = 5;
alive = true;
}
Organism(int strength1, int strength2, int speed1, int speed2)
{
Random gen = new Random();
int speedMod = gen.nextInt(((int)Math.ceil((speed1+speed2)/10.0))+1);
int speedSign = gen.nextInt(2);
if (speedSign == 0)
speedSign--;
speedMod *= speedSign;
//System.out.println(speedMod);
int strengthMod = gen.nextInt(((int)Math.ceil((strength1+strength2)/10.0))+1);
int strengthSign = gen.nextInt(2);
if (strengthSign == 0)
strengthSign--;
strengthMod *= strengthSign;
//System.out.println(strengthMod);
strength = (((int)((strength1+strength2)/2.0))+ strengthMod);
speed = (((int)((speed1+speed2)/2.0))+ speedMod);
alive = true;
life = 5;
}
}
The problem lies in the graphOrgs class when I try to print to check if it is working in preparation for graphing the results. This is when it returns the error. When I try placing the print code in other places in the Simulator class the same thing occurs, a null pointer error. This happens even if it is just after the for loop where the element has been established.
You have code that sets to null elements in your allOrgs array.
allOrgs[partner1] = null;
allOrgs[partner2] = null;
Your orgGenerations list contains the same allOrgs instance multiple times.
Therefore, when you write allOrgs[partner1] = null, the partner1'th element becomes null in all the list elements of orgGenerations, which is why the print method fails.
You should create a copy of the array (you can use Arrays.copy) each time you add a new generation to the list (and consider also creating copies of the Organism instances, if you want each generation to record the past state of the Organisms and not their final state).

Categories