Infinite while loop, can't understand why - java

I've started learning programming just recently at my university, so far we are battling with Java. Our task is to do a simulation of different processor algorithms like fcfs, sjf etc. I've tried many approaches and the one you see below is probably the least optimized. I'm aware, that this code might not be the greatest, as well as algorithm itself, but I wanted to see if it work as intended and I found a problem, that I can't really understand for a little too long and I won't be able to sleep until I find out what is wrong with it.
In the code below you will find a while loop with comment line "Why is this loop inifnite" written in caps. I have no idea why it never stops (I ran some printing tests and I know that this is the loop that is going on forever) and it is really getting on my nerves (most likely because the solution is really easy now).
Some explanation: I create a list of processes, that I then execute some methods on. Process is described by: execution time (execTime); time, that it needed to wait to start getting executed (waitTime); at what time it is ready to be executed (inTime) (but might be waiting for other process to finish executing) and id. I execute process by reducing it's execTime until it reaches 0, then I remove the process and do the same for "new first one". And this reducing part is when the program go to infinity.
Mango
import java.util.ArrayList;
import java.util.List;
public class Processor {
List<Process> listOP = new ArrayList<Process>();
int processorTime = 0;
int totalWaitTime = 0;
int numberOfProcesses = 0;
public Processor(){
for(int i=0; i<100; i++){
listOP.add(new Process(i));
if(i>0)
listOP.get(i).inTime += listOP.get(i-1).inTime + (int)((Math.random() + 0.1)*10);
System.out.println("Proces " + (listOP.get(i).id + 1) + " czas wejścia " + listOP.get(i).inTime);
}
}
public double fcfs(){
numberOfProcesses = listOP.size();
while(listOP.size() != 0){
if(listOP.get(0).inTime > processorTime){
for(int i=0; i<listOP.size(); i++){
listOP.get(i).waitTime = 0;
}
}
totalWaitTime += listOP.get(0).waitTime;
while(listOP.get(0).execTime != 0){//**WHY IS THIS LOOP INFINITE**
for(int i=1; i<listOP.size(); i++){
if(processorTime == listOP.get(i).inTime)
listOP.get(i).waitTime++;
}
listOP.get(0).execTime--;
processorTime++;
}
processorTime++;
listOP.remove(0);
}
System.out.println(totalWaitTime);
System.out.println(numberOfProcesses);
System.out.println(processorTime);
System.out.println("Średni czas tego ciągu procesów: " + totalWaitTime/numberOfProcesses);
return totalWaitTime/numberOfProcesses;
}
}

Related

Multithreading with a While Loop

So below is my code where Buyers and Sellers interact with Cars and a Car Showroom. It runs as it should, as far as I know. However, Threads only run after day 20+ in the While Loop in Main. Could anyone help point out why this is?
public static void main(String[] args) {
CarShowroom carShowroom = new CarShowroom();
Random rand = new Random();
int day = 1;
while (day <= 30){
System.out.println("Day " + day + " beginning. There are " + carShowroom.getCars().size() + " cars in the showroom today.");
int randomSeller = rand.nextInt(3);
int randomBuyer = rand.nextInt(3);
for (int j = 0; j <= randomSeller; j++){
Seller seller = new Seller(carShowroom);
Thread mySellerThread = new Thread(seller);
mySellerThread.start();
}
for (int i = 0; i <= randomBuyer; i++){
Buyer buyer = new Buyer(carShowroom);
Thread myBuyerThread = new Thread(buyer);
myBuyerThread.start();
}
day++;
}
}
}
I think perhaps your loop is executing quicker than Thread.start() will start.
It is either caused by the fact that spawned threads are not immediately ready to execute code or simply you might have single core machine and main thread occupies cpu then the other threads have to wait until cpu time slice assigned to the main thread ends. In order to achieve tiny bit of determinism within yours program execution, you could put Thread.sleep(100) in the main loop to create an opportunity for the other threads to run. That should alter the order of execution.
If I understand task correctly, then buyers and sellers should make some deals before the day ends and then new day should start (not earlier).
If so then using Thread.sleep is bad solution here for two reasons
If you set short delay then new day may start when deals are not done yet
If you set long delay (and in real prod environment it is quite a task to determine what is long enough to cover all possible future scenarios) then in most cases you will waste thread (*) + your code could be visible slow
Proper solution will be not guessing if deals are done or not but waiting for the event "all deals are done".
It could be achieved in a multiple ways (CountDownLatch, atomic counter etc) but easiest is to wait when all threads started for a day are stopped
while (day <= 30){
System.out.println("Day " + day + " beginning. There are " + carShowroom.getCars().size() + " cars in the showroom today.");
int randomSeller = rand.nextInt(3);
int randomBuyer = rand.nextInt(3);
List<Thread> allThreads = new List<>(randomSeller+randomBuyer+2);
for (int j = 0; j <= randomSeller; j++){
Seller seller = new Seller(carShowroom);
Thread mySellerThread = new Thread(seller);
mySellerThread.start();
allThreads.add(mySellerThread);
}
for (int i = 0; i <= randomBuyer; i++){
Buyer buyer = new Buyer(carShowroom);
Thread myBuyerThread = new Thread(buyer);
myBuyerThread.start();
allThreads.add(myBuyerThread);
}
for (Thread t : allThreads) {
t.join();
}
// "all deals are done"
day++;
}
t.join causes main thread (which loops the days) to wait until thread is done (== seller.run() or buyer.run() methods are completed). If thread is already finished then t.join is also safe, it will just exit.
Once you verified all sellers and buyers threads are done, you know "all deals are done"
(*) For example, if your days loop is executed in the thread taken from the pool then while you are doing sleep thread does not do any job and cannot be used for any other task as well.

Time how long a function runs (short duration)

I'm relatively new to Java programming, and I'm running into an issue calculating the amount of time it takes for a function to run.
First some background - I've got a lot of experience with Python, and I'm trying to recreate the functionality of the Jupyter Notebook/Lab %%timeit function, if you're familiar with that. Here's a pic of it in action (sorry, not enough karma to embed yet):
Snip of Jupyter %%timeit
What it does is run the contents of the cell (in this case a recursive function) either 1k, 10k, or 100k times, and give you the average run time of the function, and the standard deviation.
My first implementation (using the same recursive function) used System.nanoTime():
public static void main(String[] args) {
long t1, t2, diff;
long[] times = new long[1000];
int t;
for (int i=0; i< 1000; i++) {
t1 = System.nanoTime();
t = triangle(20);
t2 = System.nanoTime();
diff = t2-t1;
System.out.println(diff);
times[i] = diff;
}
long total = 0;
for (int j=0; j<times.length; j++) {
total += times[j];
}
System.out.println("Mean = " + total/1000.0);
}
But the mean is wildly thrown off -- for some reason, the first iteration of the function (on many runs) takes upwards of a million nanoseconds:
Pic of initial terminal output
Every iteration after the first dozen or so takes either 395 nanos or 0 -- so there could be a problem there too... not sure what's going on!
Also -- the code of the recursive function I'm timing:
static int triangle(int n) {
if (n == 1) {
return n;
} else {
return n + triangle(n -1);
}
}
Initially I had the line n = Math.abs(n) on the first line of the function, but then I removed it because... meh. I'm the only one using this.
I tried a number of different suggestions brought up in this SO post, but they each have their own problems... which I can go into if you need.
Anyway, thank you in advance for your help and expertise!

While loop doesn't continue even though condition still holds true

I was tasked to create a simulation of a Bank. So far the progress I've made are generating random Client objects, making 4 objects of Teller, putting the Client objects into a circular queue and putting a Client into an empty Teller if there are any.
The problem I have now is that the while loop I made does no continue even though the set condition is still true, it can only execute 5 times. The program still runs though.
This is the code I have so far(assume all variables are declared):
public void run() {
int counter = 1;
populateTellers(windowArray);
while (counter < 10) {
newClient = generateClient();
System.out.println(newClient.toString() + " arrived at :" + counter);
System.out.println();
clientQueue.enqueue(newClient);
clientList.add(newClient);
System.out.println("The Queue now contains " + clientQueue.numberOfOccupiedCells() + " Client(s):");
for (int x = 0; x < clientList.size(); x++) {
System.out.println(clientList.get(x).toString());
}
System.out.println();
arrayIndex = getATeller(windowArray);
if (arrayIndex != -1) {
clientList.remove(0);
clientQueue.dequeue();
windowArray[arrayIndex].setClient(newClient);
windowArray[arrayIndex].setServiceTime(newClient.getDuration());
System.out.println(windowArray[arrayIndex].getName() + " now serves " + newClient.toString());
} else {
for (int x = 0; x < clientList.size(); x++) {
if (windowArrray[arrayIndex].getServiceTime() == counter) {
windowArray[arrayIndex].setClient(new Client());
System.out.println(windowArray[arrayIndex].getName() + " ends service for " + newClient.toString());
}
}
}
counter++;
}
}
The one thing that I can't get head around is that when I remove the code from aI = getATeller(wA); 'till the closing bracket of the if statement below it the program would work. I've tried putting the block into a method, changing the positions of the codes inside if(){} and else{} and changing the condition to if(aI==1), still I got no improvements. Any idea on what I'm doing wrong?
EDIT: So I've been able to narrow it down to a line of code which is windowArray[arrayIndex].setServiceTime(newClient.getDuration());, whenever I assign a value to a Teller's service time the problem would occur, I've checked my Teller class and there was no error there. Any ideas how I can solve this.
Why is it only executing 5 times? According to the code, counter is used as the used to check if it should continue looping for not. The only instance where counter is changed is at last line: counter++.
I can guess that you did a System.out.print on the counter, and it ends up to 5, and it magically stops. Most likely it's throwing an exception, which is not caught, and is lost in the void.
Edit: If this piece of code is being run on another thread, then maybe it's hanging up on some function. Do as told here
Try to find where your loop was turning to infinite loop,
Try writing printing statements, wherever necessary, just to find the flow of execution.
Then printout your variable values, too check whether they were as expected, keep on narrowing your scope as you find error occurred in certain scope, then you will find the culprit, if it is leading you to some other function, then thoroughly check that particular function.

Java Bubble Sort Iterates Only Twice

I'm in an intro to Java course and am just trying to get ahead of the curve with some practice, so I'm making a bubble sort program. For some reason, it only will run through the outer loop twice.
public ArrayList SortArray(ArrayList<Integer> u) {
int temp;
int spot;
for (int isOrdered = 1; isOrdered == 1;) {
for (spot = 0; spot < u.size() - 1; spot ++) {
System.out.println(u.get(spot) + " " + u.get(spot + 1) + " " + spot);
if (u.get(spot) > u.get(spot + 1)) {
temp = u.get(spot + 1);
u.set(spot + 1, u.get(spot));
u.set(spot, temp);
isOrdered = 1;
}
else {
isOrdered = 0;
}
}
}
return u;
}
As far as I can tell, what's happening is after the second iteration, it doesn't reset 'spot' to 0 so it doesn't run through the loop again. Any ideas?
Well, for starters that's an ... unusual way of using a for loop to implement a while loop. Try using a boolean for isOrdered and a while(!isOrdered) for a statement like that.
As Ted Hopp's comment said, your logic isn't quite right. What your code is doing is that it will sort ONE value in the list and once that value has "bubbled up" your flag is set to true.
You need your outer loop's condition to be that it keeps running until ALL cells are in order.
Right now your flag simply says it's sorted, when you've gone through the list, but what it needs to do is be true when it's gone through the list without performing a swap.
Try to implement that without looking, then if you can't get it (I'm assuming you're interested in doing it yourself since you're working ahead in your class) take a look at the sample here.

How should I parallelize a computationally expensive for loop and collate the iteration results?

I'm working on an 8-core machine and am performing a computationally heavy task. However, each execution of the task (i.e., iteration of for loop) is rather independent of the previous one. There are only some variables that are 'summed up' from one execution to the next. I'm guessing this is a good example for parallelizing/threading but I'm not sure how to go about it.
Here's how the code looks. As of now, it's just part of the main method in my main executor class:
double testerPayoffSum = 0.0, developerPayoffSum = 0.0;
Random seed = new Random();
try {
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
testerPayoffSum += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
System.out.print("Output: ERASER Games played; Number of developers caught");
System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
} catch(Exception e){sendEmailAlert("Execution Failed with Exception");}
I'd like to parallelize the for-loop computation if possible and keep summing up the testerPayoffSum and developerPayofffSum variables. How might I achieve this?
Note: Each execution of the for loop takes about 20-30 minutes depending on the input size (as set by the various GameConstants). Even for a small number of MAX_GAMES the above takes close to 2-3 hours.
Create a thread object implementing Callable which returns a Future object containing your testerPayoffSum and developerPayoffSum, start the calculation and sum the results obtained from the Futures (See also https://blogs.oracle.com/CoreJavaTechTips/entry/get_netbeans_6).
are you absolutely sure you have no dependency ?
1.used classes must not share any variables
if it does then you have to add locks
but it will affect performance
if some shared variables are used extensively
then the performance can drop significantly even bellow the non-parallel execution
2.used classes must not use any kind of machine learning.
there is no solution for this
because parallelization will corrupt your results
Now how to do it (I am not JAVA coder so I stick to C++ code).
//--- globals and headers -----------------------------------------------------
unsigned long __stdcall function(LPVOID p);
Random seed = new Random();
const int N=8; // threads count (<=CPU count)
int id[N]; // thread id
int max[N]; // number of games per thread
double testerPayoffSum[N]; // sum to separate variables to avoid locks need
double developerPayoffSum[N];
volatile int run=0,stop=0; // thread control variables run is number of running threads and stop force stop...
//--- main code ---------------------------------------------------------------
// init some variables ... may be the seed init will be better here too
int i;
for (i = 0; i < N; i++)
{
id[i]=i;
max[i]=GameConstants.MAX_GAMES / N;
testerPayoffSum[i]=0.0;
developerPayoffSum[i]=0.0;
}
max[0]=GameConstants.MAX_GAMES % N;
// create threads
for (i = 0; i < N; i++)
{
HANDLE hnd=CreateThread(0,0,function,&id[i],0,0);
if (hnd!=NULL) CloseHandle(hnd); // this line is important !!!
// because if you do not close Handle it will be allocated until the end of app
// handle leaks are nasty and cause weird OS behaviour
// I saw many times this bug in commercial drivers
// it is a nightmare for 24/7 software
}
// wait for them
while (run) Sleep(200);
// sum the results to [0]
for (i = 1; i < N; i++)
{
testerPayoffSum[0] +=testerPayoffSum[i];
developerPayoffSum[0]+=developerPayoffSum[i];
}
// here do what you need to do with the results
//--- thread function ---------------------------------------------------------
unsigned long __stdcall function(LPVOID p)
{
run++;
int ix=((int*)p)[0];
for (i = 0; i < max[ix]; i++)
{
if (stop) break;
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
testerPayoffSum[ix] += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum[ix] += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
// do not call any visual stuff from thread !!! sometimes it can cause a lot of problems ...
// instead cretae some global string variable and set it to what shoud be printed out
// and inside wait while loop in main code add if string != "" then System.out.print(string);
// but in that case you should add lock to it.
// System.out.print("Output: ERASER Games played; Number of developers caught");
// System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
//Sleep(100); // well placed sleep
}
run--;
}
[Notes]
from your code I am assuming that GameConstants is shared variable !!!
if it is only for read than it is OK
but if you do also write to it inside thread (I suspect that yes)
then you have a big problem because you need to add locks inside your game class then ...
if no machine learning is done then you could avoid this
by creating separate GameConstants variables for each thread like ... GameConstants[N]
but you need to rewrite the code so it access the GameConstants[ix] and not GameConstants
[lock]
have no clue how locks are implemented in JAVA
but you can also use your own something like this
class _lock
{
public:
volatile bool locked;
_lock() { locked=false; }
void lock() { while(locked) Sleep(1); locked=true; }
void unlock() { locked=false; }
};
// now for each shared variable (or group of variables) add one global _lock variable
_lock l1; int sv1; // shared variable 1 and her lock
// any write access and sometimes also read access needs lock
l1.lock();
sv1++;
l1.unlock();
beware that locks can sometimes cause App freeze especially while heavy duty use.
does not matter if it is own lock or OS lock
this occurs mainly while mixing visual stuff or some OS calls inside threads and not in main thread
in that case sometimes a well placed sleep helps but avoid OS calls inside threads if you can
because it cause very many other problems ...
also try to be locked as small time as possible because in case of conflict the conflicting threads are stopped !!!
therefore you cannot just add lock at the start of loop and unlock at the end
because the parallelism speedup will be lost then
Declare a queue to collect results and submit tasks to a thread pool:
final ArrayBloclingQueue<PlayerPayoffs> queue=new ArrayBloclingQueue<PlayerPayoffs>();
Executor exec=new Executors.newFixedThreadPool(N); // number of threads depends on hardware
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
exec.execute(new Runnable(){
EraserSimulator eraser = new EraserSimulator(GameConstants.MAX_TARGETS, GameConstants.MAX_RESOURCES, GameConstants.NUM_ATTACKER_TYPES, seed.nextInt());
Map<Set<SingleObjectiveTarget>, Double> gameStrategy = eraser.run();
assert (gameStrategy != null);
TestingGameSimulator testingGame = new TestingGameSimulator(GameConstants.MAX_TARGETS, gameStrategy, GameConstants.NUM_GAMES_TO_STORE_FOR_HISTORY, GameConstants.NUM_TESTING_GAMES_TO_PLAY);
PlayerPayoffs payoffs = testingGame.run(eraser.getEraserInstance());
queue.put(payoffs);
});
}
Then collect and sum results:
double testerPayoffSum = 0.0, developerPayoffSum = 0.0;
for (int i = 0; i < GameConstants.MAX_GAMES; i++) {
PlayerPayoffs payoffs=queue.take();
testerPayoffSum += payoffs.getAverageTesterPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
developerPayoffSum += payoffs.getAverageDeveloperPayoff(GameConstants.NUM_TESTING_GAMES_TO_PLAY);
System.out.print("Output: ERASER Games played; Number of developers caught");
System.out.print(", " + GameConstants.NUM_TESTING_GAMES_TO_PLAY + ", " + payoffs.getNumTimesCaught() + "\n");
}

Categories

Resources