Run each loop at a different time interval - java

I'm currently working on a program that pits two simulated fighters against one another. The way I have it right now, each round is done and the output is printed all at once (virtually all at once because it is calculated so fast).
How would I take the below code and make it so that actions in the second loop occur in pseudo real time where it executes x amount of seconds where x is a random roll? Any suggestions or guidance would be great. I would even settle for the second while loop executing every three seconds or so. This is a prototype for now and the simulation will get more varied so reading the output may get more interesting.
public static void fight(Character player1, Character player2, int roundMax){
player1.setTempHitPoints(player1.getHitPoints());
player2.setTempHitPoints(player2.getHitPoints());
int r = ROUND;
while(!isFightOver(player1, player2)){
roundTimer = 0;
System.out.println("================");
System.out.println("Round " + r + " FIGHT!");
System.out.println("================");
while(roundTimer < roundMax && !isFightOver(player1, player2)){
roundTimer = roundTimer + Commands.roll(10);
round(player1, player2);
timerPrint(roundTimer, roundMax);
}
System.out.println("================");
System.out.println("Round " + r + " OVER!");
System.out.println("================");
System.out.println("");
if(!isFightOver(player1, player2)){
Commands.rest(player1);
Commands.rest(player2);
}
System.out.println("");
r++;
}
declareWinner(player1, player2);
}

You can use Thread.sleep() to slow down the processing.
E.g. Thread.sleep(1000) causes the current thread to suspend execution for a second (1000 ms). Can you use that method judiciously to put delays into the code? You can use java.util.Random to generate random numbers.
Random random = new Random();
Thread.sleep((random.nextInt(6) + 1) * 1000); // Delays from 1 - 6 secs

Related

Creating a Call Simulator

The number of calls received per minute at a Help Desk has been estimated to be between 5 and 10.
Write a simulation program that simulates calls arriving at the Help Desk for a period of 12 hours and output the frequency of calls during this period.
Sample output:
(Note: The frequencies for your program will be different from the ones shown below. Each time you run your program, you should get different frequencies)
Calls/Minute Frequency
5 155
6 172
7 148
8 123
9 62
10 60
This is what I've came up with, but cannot figure out how to split/leave a gap between calls/minute and frequency. Basically splitting it into two rows.
import java.util.Random;
public class randomCalls {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
Random rn = new Random();
int n;
for(int i=1;i<=6;i++)
{
n = rn.nextInt(6) +5;
System.out.println("Calls/Minute" +"\n" + n);
System.out.print(' ');
System.out.println(" Frequency" + "\n"+ i);
}
}
}
I'm pretty sure you are trying to print out Calls/Minute and Frequency in columns. Here is a helpful link.
In order to use that method your need to...
Combine the lines System.out.println("Calls/Minute" +"\n" + n); and System.out.println(" Frequency" + "\n"+ i);, and format the resulting single line so that it is split into two columns.
//Example
System.out.printf("%-12.30s %-30.30s%n","Column 1","Column 2");
Place it BEFORE your for loop (or else it will print every time)
Within your for loop, format your output exactly the same as you did the line in step one.
//Example
System.out.printf("%-12.30s %-30.30s%n",n,i);
Sample output in your program would look like this:
Calls/Minute Frequency
6 1
7 2
8 3
8 4
9 5
6 6
Here is how I got it to print like described:
Random rn = new Random();
int n;
for(int i=1;i<=6;i++) {
n = rn.nextInt(6) +5;
System.out.println( n + " " + i );
Hope this helps!

How to make a counter persist in Java?

I'm making a dice game that scores points based on rolling a 7 or 11(pair of dice). The game keep track of the bets and score. The current score should be added to 3 times the bet amount if the the condition is met. However the score only changes the in the first instance the condition is met, then remain the same through any other roll attempts. I tried to set my getters and setters to be static but that didn't work. What can I do to make my counter work properly?
Program:
public Game() {
final Dice throwDice = new Dice();
//Roll Dice
rollDice.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
throwDice.PairOfDice();
diceResult.setText("You rolled: " + throwDice.getDie1() +
" + " + throwDice.getDie2() +
" = " + throwDice.getTotal());
currentScore.setText("Score: $" + throwDice.getScore());
if(throwDice.getTotal() == 7 || throwDice.getTotal() == 11) {
throwDice.setScore(Integer.parseInt(input.getText()) * 3);
currentScore.setText("Score: $" + throwDice.getScore());
}
}
});
The declaration of your Dice:
Dice throwDice = new Dice();
is in actionPerformed() which means it is created every time you call that function.
Move the declaration into Game, ie. make it an attribute of a game and you should be fine.
You can safely make Dice::score, Dice::getScore() and Dice:setScore(int) non-static.
UPDATE: Given there is still an issue, perhaps try replacing:
throwDice.setScore(Integer.parseInt(input.getText()) * 3);
with:
throwDice.setScore(throwDice.getScore() + (3 + throwDice.getBet()));
In your question you say:
The current score should be added to 3 times the bet amount
You are not adding to the current score. You are only setting the score to the 3 times the bet amount every time. So the value will not change (unless, of course, you change the bet amount).
throwDice.setScore(Integer.parseInt(input.getText()) * 3)
Instead you need to add it to the current score:
throwDice.setScore(throwDice.getScore() + Integer.parseInt(input.getText()) * 3)
You need to move
Dice throwdice = new Dice`
up the code so that it is not called every time it enters actionperformed

I can't identify the issue with my parallel run timer

I have a program that applies a median filter to an array of over 2 million values.
I'm trying to compare run times for sequential vs parallel on the same dataset. So when I execute the program, it does 20 runs, every run is timed, and an average of the 20 times is outputted to the console.
ArrayList<Double> times = new ArrayList<>(20);//to calculate average run time
for (int run = 1; run < 21; run++) //algorithm will run 20 times
{
long startTime = System.nanoTime();
switch (method)
{
case 1: //Sequential
filt.seqFilter();
break;
case 2: //ForkJoin Framework
pool.invoke(filt); //pool is ForkJoin
break;
}
Double timeElapsed = (System.nanoTime() - startTime) / 1000000.0;
times.add(run - 1, timeElapsed);
System.out.println("Run " + run + ": " + timeElapsed + " milliseconds.");
}
times.remove(Collections.max(times)); //there's always a slow outlier
double timesSum = 0;
for (Double e : times)
{
timesSum += e;
}
double average = timesSum / 19;
System.out.println("Runtime: " + average);
filt is of type FilterObject which extends RecursiveAction. My overridden compute() method in FilterObject looks like this:
public void compute()
{
if (hi - lo <= SEQUENTIAL_THRESHOLD)
{
seqFilter();
}
else
{
FilterObject left = new FilterObject(lo, (hi + lo) / 2);
FilterObject right = new FilterObject((hi + lo) / 2, hi);
left.fork();
right.compute();
left.join();
}
}
seqFilter() processes the values between the lo and hi indices in the starting array and adds the processed values to a final array in the same positions. That's why there is no merging of arrays after left.join().
My run times for this are insanely fast for parallel - so fast that I think there must be something wrong with my timer OR with my left.join() statement. I'm getting average times of around 170 milliseconds for sequential with a filtering window of size 3 and 0.004 milliseconds for parallel. Why am I getting these values? I'm especially concerned that my join() is in the wrong place.
If you'd like to see my entire code, with all the classes and some input files, follow this link.
After some testing of your code I found the reason. It turned out that the ForkJoinPool runs one task instance only once. Subsequent invoke() calls with the same task instance will return immediately. So you have to reinstantiate the task for every run.
Another problem is with the parallel (standard threads) run. You are starting the threads but never waiting for them to finish before measuring the time. I think You could use the CyclicBarrier here.
With the mentioned fixes I get roughly the same time for ForkJoin and standard threads. And it's three times faster than sequential. Seems reasonable.
P.S. You are doing a micro-benchmark. It may be useful to read answers to that question to improve your benchmark accuracy: How do I write a correct micro-benchmark in Java?

How to get loop to stop

I need help or some ideas on how to get the loop in this code to stop executing when the speedUp factor settles to a particular value. The idea of this method is continually run an ever increasing number of threads and derive a speedUp factor from the results. The rounded speedUp factor is how many cores are present on the machine. Running a 4 threaded task will have the same speedUp factor as a 16 threaded task on a 4 core machine. I want to be able to not have to manually set number of threads to run. When the speedUp factor settles to a value I want the program to terminate. There is no need to run a test for 8, 16, or 32 threads if the speed up factor has already settled at 2 for example.
Example output for a 4 core machine:
Number of threads tested: 1
Speed up factor: 1.0
Number of threads tested: 2
Speed up factor: 1.8473736372646188
Number of threads tested: 4
Speed up factor: 3.9416666666666669
Number of threads tested: 8
Speed up factor: 3.9750993377483446
Number of threads tested: 16
Speed up factor: 4.026086956521739
THIS MACHINE HAS: 4 CORES
THE APPLICATION HAS COMPLETED EXECUTION. THANK YOU
private static void multiCoreTest() {
// A runnable for the threads
Counter task = new Counter(1500000000L);
// A variable to store the number of threads to run
int threadMultiplier = 1;
// A variable to hold the time it takes for a single thread to execute
double singleThreadTime = ThreadTest.runTime(1, task);
// Calculating speedup factor for a single thread task
double speedUp = (singleThreadTime * threadMultiplier) / (singleThreadTime);
// Printing the speed up factor of a single thread
System.out.println("Number of threads tested: " + threadMultiplier);
System.out.println("Speed up factor: " + speedUp);
// Testing multiple threads
while (threadMultiplier < 16) {
// Increasing the number of threads by a factor of two
threadMultiplier *= 2;
// A variable to hold the time it takes for multiple threads to
// execute
double multiThreadTime = ThreadTest.runTime(threadMultiplier, task);
// Calculating speedup factor for multiple thread tests
speedUp = (singleThreadTime * threadMultiplier) / (multiThreadTime);
// Message to the user
System.out.println("\n" + "Number of threads tested: "
+ threadMultiplier);
System.out.println("Speed up factor: " + speedUp);
}
// Print number of cores
System.out.println("\n" + "THIS MACHINE HAS: " + Math.round(speedUp)
+ " CORES");
System.out.println("\n"
+ "THE APPLICATION HAS COMPLETED EXECUTION. THANK YOU");
// Exiting the system
System.exit(0);
}
}
Test if the new speedup is the same as the old one:
double oldSpeedUp = 0;
boolean found = false;
while(!found && threadMultiplier < 16) {
// ...
found = Math.round(speedUp) == Math.round(oldSpeedUp);
oldSpeedUp = speedUp;
}
As a side note, if you want the number of cores, you can call :
int cores = Runtime.getRuntime().availableProcessors();

Simple concurrent Java threads--capture begin and end

Am I correctly implementing these Java threads? The goal is to have ten concurrent threads who compute a sum from 1 to (upper bound 22 + i). I'm trying to identify the name and print it when running the thread, then print the result when the thread exits. Currently, I have all of the results printing at the same time in a random order and I am not sure if I am correctly getting the information when the thread begins and ends.
public class threads {
public static void main(String[] args) {
for(int i = 0; i < 10; i++) {
final int iCopy = i;
new Thread("" + i) {
public void run() {
int sum = 0;
int upperBound = 22;
int lowerBound = 1;
long threadID = Thread.currentThread().getId();
for (int number = lowerBound; number <= upperBound; number++){
sum = sum + number + iCopy;
}
System.out.println(threadID + " thread is running now, I and will compute the sum from 1 to " + (upperBound + iCopy) + ". The i is : " + iCopy);
System.out.println("Thread id #" + threadID + ", the "+ sum + " is done by the thread.");
}
}.start();
}
}
}
I have executed your code and observed that all threads are running properly 10 in this case. Since threads are invoked in random order that is why this behavior might be seen but I an sure that all threads for running fine and executing the functionality you require.
Any how in output i saw that in for loop the value should start from 0 to 9 but here even this is random, may be because some threads are sleeping while executing and giving way to other threads.
Hope this helps
Thanks.
The order the threads run in will depend entirely on the JVM being used and underlying resources.
If you have several cores (cpus) available, your code may run completely differently to a single core.
Essentially, your main loop runs to the end in a single thread, firing 10 new threads, and puts the start method in a process queue. Other processors may start running those threads. Each extra thread causes different total load, so they run slightly differently (performance wise) on each processor, meaning they run faster/slower, and end in different times.
Your code demonstrates this very well.

Categories

Resources