been working on this program for a while and I think I've made much more progress. My java skills are not very good, but I think I'm close. Everything should compile without issue except for my "public void run" in my worker class. The program prompts the user for how many threads they want and then parses through a text file of random numbers to find all the prime numbers. My issue seems to be in the algorithm for the prime numbers. How do I write the algorithm so it parses the data down and finds the prime numbers?
I have posted the entire program below, but please see the worker class towards the bottom. Any help would be greatly appreciated in solving this issue. Thank you.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.util.Scanner;
public class PrimeNumbers{
public static void main(String[] args) throws IOException {
int[] numbers = new int[100000];
int count;
int index = 0;
String datafile = "dataset529.txt"; //string which contains datafile
String line; //current line of text file
try (BufferedReader br = new BufferedReader(new FileReader(datafile))) { //reads in the datafile
while ((line = br.readLine()) != null) { //reads through each line
numbers[index++] = Integer.parseInt(line); //pulls out the number of each line and puts it in numberset[]
}
}
System.out.println("How many threads would you like to use?");
Scanner scan = new Scanner(System.in);
int z = scan.nextInt();
Thread[] threads = new Thread[z]; //creates threads as per user
worker[] finder = new worker[z]; //assigns finder to each thread created
int range = numbers.length / z; //breaks up each worker into a section depending on thread count.
for (count = 0; count < z; count++) {
int startAt = count * range;
int endAt = startAt + range;
finder[count] = new worker(startAt, endAt, numbers);
}
for (count = 0; count < z; count++) { //moves to next thread
threads[count] = new Thread(finder[count]);
threads[count].start();
}
boolean processing = false;
do {
processing = false;
for (Thread t : threads) {
if (t.isAlive()) {
processing = true;
break;
}
}
} while (processing);
for (worker worker : finder) {
System.out.println("Max of thread is: " + worker.getPrime());
}
}
public static class worker implements Runnable {
private int start;
private int stop;
private int numberset[];
public worker(int start, int stop, int[] numberset) {
this.start = start;
this.stop = stop;
this.numberset = numberset;
}
#Override
public void run() {
for (int x = start; x < stop; x++) {
if (numberset[]%3 && != 1 && != 2 && !=3)
return prime
}
}
public int getPrime() {
return true
}
}
}
Related
I have been tasked to solve a question concerning the creation of a triple-ended queue with efficient random access, as outlined in this: https://open.kattis.com/problems/teque. I created a program based around using 2 very large arrays, one containing the front half of all stored integers so far and the other the back half, with both being of the same size or the front half containing at most 1 more element than the back half after every insertion operation. This should allow all insertion and retrieval operations to be of O(1) time complexity, but the code just keeps exceeding the given time limit. Can anyone tell me what is wrong with my code? Here it is:
import java.util.*;
import java.io.*;
public class Teque3 {
static int[] front = new int[1_000_000];
static int[] back = new int[1_000_000];
static int frontHead = 499_999;
static int backHead = 499_999;
static int frontSize = 0;
static int backSize = 0;
public static void main(String[] args) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
int n = Integer.parseInt(br.readLine());
for (int i = 0; i < n; i++) {
String[] line = br.readLine().split(" ");
if (line[0].equals("get")) {
int index = Integer.parseInt(line[1]);
if (index >= frontSize) System.out.println(back[backHead + index - frontSize]);
else System.out.println(front[frontHead + index]);
continue;
}
if (frontSize == backSize) {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
frontSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
front[frontHead + frontSize] = back[backHead];
frontSize++;
backHead++;
} else if (line[0].equals("push_middle")) {
front[frontHead + frontSize] = Integer.parseInt(line[1]);
frontSize++;
}
} else {
if (line[0].equals("push_front")) {
frontHead--;
front[frontHead] = Integer.parseInt(line[1]);
backHead--;
back[backHead] = front[frontHead + frontSize];
backSize++;
} else if (line[0].equals("push_back")) {
back[backHead + backSize] = Integer.parseInt(line[1]);
backSize++;
} else if (line[0].equals("push_middle")) {
backHead--;
back[backHead] = Integer.parseInt(line[1]);
backSize++;
}
}
}
}
}
You could try to minimze IO-Operations: Collect your programm output. Instead of writing System.out.println better create a new StringBuilder to collect everything. In the end write all at once.
static StringBuilder result = new StringBuilder();
...
private static void result(int value) {
result.append(value).append("\n");
}
...
if (index >= frontSize) result(back[backHead + index - frontSize]);
else result(front[frontHead + index]);
...
System.out.println(result);
Decouple read from parse and process: Create one thread for reading the operations. But the operations in a Queue. Start another thread for the process.
I am trying to do a multi threading simulation in Java and I have managed to do it with a queue but the execution time is high, any ideas on how I could optimize this? Can using recursion save time?
The input has to be like this:
2 5 It means that there are two threads(workers) for 5 jobs
1 2 3 4 5 This is the jobs that are an integer which means the time cost of processing that job so the output will be this:
0 0 The two threads try to simultaneously take jobs from the list, so thread with index 0 actually
1 0 takes the first job and starts working on it at the moment 0
0 1 After 1 second, thread 0 is done with the first job and takes the third job from the list, and starts processing it immediately at time 1.
1 2 One second later, thread 1 is done with the second job and takes the fourth job from the list, and starts processing it immediately at time 2
0 4 Finally, after 2 more seconds, thread 0 is done with the third job and takes the fifth job from the list, and starts processing it immediately at time 4
This is the code:
import java.io.*;
import java.util.HashMap;
import java.util.HashSet;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.StringTokenizer;
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private FastScanner in;
private PrintWriter out;
public static void main(String[] args) throws IOException {
new JobQueue().solve();
}
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void writeResponse() {
for (int i = 0; i < jobs.length; ++i) {
out.println(assignedWorker[i] + " " + startTime[i]);
}
}
private void assignJobs() {
// TODO: replace this code with a faster algorithm.
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
public void solve() throws IOException {
in = new FastScanner();
out = new PrintWriter(new BufferedOutputStream(System.out));
readData();
assignJobs();
writeResponse();
out.close();
}
static class FastScanner {
private BufferedReader reader;
private StringTokenizer tokenizer;
public FastScanner() {
reader = new BufferedReader(new InputStreamReader(System.in));
tokenizer = null;
}
public String next() throws IOException {
while (tokenizer == null || !tokenizer.hasMoreTokens()) {
tokenizer = new StringTokenizer(reader.readLine());
}
return tokenizer.nextToken();
}
public int nextInt() throws IOException {
return Integer.parseInt(next());
}
}
}
It seems to me that your jobsList object is completely redundant, everything it contains is also in the jobs array and when you take the front element you get the item at jobs[i]. To speed up a little you could take the constructors of the ints out of the loop and just assign new numbers to them. Another optimization would be to not search during the first numWorkers jobs because you know you still have idle workers until you have exausted your pool. Once you have found one good worker you dont have to keep looking so you can continue out of your for-loop.
public class JobQueue {
private int numWorkers;
private int[] jobs;
private int[] assignedWorker;
private long[] startTime;
private void readData() throws IOException {
numWorkers = in.nextInt();
int m = in.nextInt();
jobs = new int[m];
for (int i = 0; i < m; ++i) {
jobs[i] = in.nextInt();
}
}
private void assignJobs() {
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
bestWorker = 0;
if (i< numWorkers){
bestWorker= i;
} else{
for (int j = 0; j < numWorkers; ++j) {
if (nextFreeTime[j] < nextFreeTime[bestWorker])
bestWorker = j;
continue;
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
However, both your solution and this slightly trimmed down one take 2 milliseconds to run. I also looked at having HashMap to maintain a NextWorker marker but at some point you catch up with it and end up looking everytime for the next one and don't win much.
You could try having an ordered List/Queue, but then you have expensive inserts instead of expensive searches, and you have to kee track of the timeslice. But a version like that could look like this:
private void assignJobs() {
assignedWorker = new int[jobs.length];
startTime = new long[jobs.length];
PriorityQueue<Integer> nextTimesQueue = new PriorityQueue<Integer>();
HashMap<Integer, Set<Integer>> workersReadyAtTimeT = new HashMap<Integer,Set<Integer>>();
long[] nextFreeTime = new long[numWorkers];
int duration = 0;
int bestWorker = 0;
for (int i = 0; i < jobs.length; i++) {
duration = jobs[i];
if(i<numWorkers) {
bestWorker = i;
nextTimesQueue.add(duration);
addToSet(workersReadyAtTimeT, duration, i,0);
}else {
int currentTime = nextTimesQueue.poll();
Set<Integer> workersReady = workersReadyAtTimeT.get(currentTime);
if (workersReady.size()>1) {
bestWorker = workersReady.iterator().next();
workersReady.remove(bestWorker);
workersReadyAtTimeT.remove(currentTime);
workersReadyAtTimeT.put(currentTime,workersReady);
nextTimesQueue.add(currentTime);
} else {
bestWorker = workersReady.iterator().next();
workersReadyAtTimeT.remove(currentTime);
nextTimesQueue.add(currentTime+duration);
addToSet(workersReadyAtTimeT, duration, bestWorker, currentTime);
}
}
assignedWorker[i] = bestWorker;
startTime[i] = nextFreeTime[bestWorker];
nextFreeTime[bestWorker] += duration;
}
}
private void addToSet(HashMap<Integer, Set<Integer>> workersReadyAtTimeT, int duration, int worker, int current) {
if(workersReadyAtTimeT.get(current+duration)==null) {
HashSet<Integer> s = new HashSet<Integer>();
s.add(worker);
workersReadyAtTimeT.put(current+duration, s);
}else {
Set<Integer> s = workersReadyAtTimeT.get(current+duration);
s.add(worker);
workersReadyAtTimeT.put(current+duration,s);
}
}
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;
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).
So, I made a small program to test Multithreading in java and compare the time it takes to scale an array using a while loop and then creating multiple threads and running those threads. I'm unsure about then numbers I'm getting when the program finishes, so I was wondering if I made a boneheaded error at some point and messed something up to get very disparate numbers.
Code below:
import java.util.Scanner;
public class arrayScaling {
public static void main(String[] args) throws InterruptedException {
Scanner input = new Scanner(System.in);
System.out.println("Enter the amount of number you want the program to generate:");
int numOfNumbs = input.nextInt();
int [] arrayForNumbers = new int [numOfNumbs];
int [] newArrayForNumbers = new int [numOfNumbs];
for (int i = 0; i < arrayForNumbers.length; i++) {
arrayForNumbers[i] = (int) ((Math.random() * 25) + 1);
}
long startTime = System.nanoTime();
for (int i = 0; i < arrayForNumbers.length; i++) {
newArrayForNumbers[i] = newArrayForNumbers[i] * 3;
}
long endTime = System.nanoTime();
System.out.println();
long totalExecutionTime = endTime-startTime;
System.out.println("Time it takes execute scaling is " +
totalExecutionTime + " nanoseconds");
System.out.println();
int numOfNumLeftOver = numOfNumbs % 5;
int numOfNumDivided = numOfNumbs / 5;
int [] temp = null;
int [] temp2 = null;
int [] temp3 = null;
int [] temp4 = null;
int [] temp5 = null;
MyThread thread1 = new MyThread (numOfNumbs/5);
MyThread thread2 = new MyThread (numOfNumbs/5);
MyThread thread3 = new MyThread (numOfNumbs/5);
MyThread thread4 = new MyThread (numOfNumbs/5);
MyThread thread5;
if (numOfNumLeftOver != 0) {
numOfNumDivided = numOfNumDivided + numOfNumLeftOver;
thread5 = new MyThread (numOfNumDivided);
}
else {
thread5 = new MyThread (numOfNumbs/5);
}
int tempNum = 0;
for ( int i = 0; i < thread1.getArray().length; i ++) {
temp = thread1.getArray();
temp[tempNum] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread2.getArray().length; i ++) {
temp2 = thread2.getArray();
temp2[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread3.getArray().length; i ++) {
temp3 = thread3.getArray();
temp3[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread4.getArray().length; i ++) {
temp4 = thread4.getArray();
temp4[i] = arrayForNumbers[tempNum];
tempNum++;
}
for ( int i = 0; i < thread5.getArray().length; i ++) {
temp5 = thread5.getArray();
temp5[i] = arrayForNumbers[tempNum];
tempNum++;
}
thread1.setArray(temp);
thread2.setArray(temp2);
thread3.setArray(temp3);
thread4.setArray(temp4);
thread5.setArray(temp5);
long startTime2 = System.nanoTime();
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread1.join();
thread2.join();
thread3.join();
thread4.join();
thread5.join();
long endTime2 = System.nanoTime();
long newTotalExecutionTime = endTime2 - startTime2;
System.out.println("Time it takes execute scaling w/ multiple threads is " +
newTotalExecutionTime + " nanoseconds");
if (newTotalExecutionTime < totalExecutionTime) {
System.out.println("Multithreading was more effective");
}
else if (totalExecutionTime < newTotalExecutionTime) {
System.out.println("The original algorithm was more effective");
}
else if (totalExecutionTime == newTotalExecutionTime) {
System.out.println("Both method worked at the same speed");
}
input.close();
}
}
public class MyThread extends Thread {
private int [] array;
private int [] scaleArray;
public MyThread(int size) {
array = new int [size];
scaleArray = new int [size];
}
public int[] getArray() {
return array;
}
public void setArray(int[] array) {
this.array = array;
}
public int[] getScaleArray() {
return scaleArray;
}
public void setScaleArray(int[] scaleArray) {
this.scaleArray = scaleArray;
}
public void run () {
for (int z = 0; z < array.length; z++){
scaleArray[z] = 3 * array[z];
}
}
}
And the output of this program is:
Enter the amount of number you want the program to generate:
16
Time it takes execute scaling is 893 nanoseconds
Time it takes execute scaling w/ multiple threads is 590345 nanoseconds
The original algorithm was more effective
Your results don't surprise me in the slightest. There's a lot of overhead to creating threads, starting them, waiting for them to finish and so on. Don't forget, 590345ns is still less than a millisecond; but most of that is to do with shuffling threads, not with multiplying the numbers.
If you want to see the threaded part of the program outperform the other part, try generating a whole lot more than 16 numbers.